mirror of
https://github.com/moparisthebest/davmail
synced 2024-12-13 03:02:22 -05:00
LdapConnection refactoring complete
git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@198 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
parent
b49b75adbd
commit
d862e9d3e0
@ -4,6 +4,7 @@ import com.sun.jndi.ldap.Ber;
|
||||
import com.sun.jndi.ldap.BerDecoder;
|
||||
import com.sun.jndi.ldap.BerEncoder;
|
||||
import davmail.AbstractConnection;
|
||||
import davmail.Settings;
|
||||
import davmail.exchange.ExchangeSessionFactory;
|
||||
import davmail.tray.DavGatewayTray;
|
||||
|
||||
@ -16,6 +17,7 @@ import java.net.SocketTimeoutException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Handle a caldav connection.
|
||||
@ -30,25 +32,44 @@ public class LdapConnection extends AbstractConnection {
|
||||
*/
|
||||
static final HashMap<String, String> ATTRIBUTE_MAP = new HashMap<String, String>();
|
||||
static {
|
||||
ATTRIBUTE_MAP.put("AN", "uid");
|
||||
ATTRIBUTE_MAP.put("EM", "mail");
|
||||
ATTRIBUTE_MAP.put("DN", "displayName");
|
||||
ATTRIBUTE_MAP.put("PH", "telephoneNumber");
|
||||
ATTRIBUTE_MAP.put("OFFICE", "l");
|
||||
ATTRIBUTE_MAP.put("CP", "company");
|
||||
ATTRIBUTE_MAP.put("TL", "title");
|
||||
ATTRIBUTE_MAP.put("uid", "AN");
|
||||
ATTRIBUTE_MAP.put("mail", "EM");
|
||||
ATTRIBUTE_MAP.put("displayName", "DN");
|
||||
ATTRIBUTE_MAP.put("telephoneNumber", "PH");
|
||||
ATTRIBUTE_MAP.put("l", "OFFICE");
|
||||
ATTRIBUTE_MAP.put("company", "CP");
|
||||
ATTRIBUTE_MAP.put("title", "TL");
|
||||
|
||||
ATTRIBUTE_MAP.put("first", "givenName");
|
||||
ATTRIBUTE_MAP.put("cn", "DN");
|
||||
ATTRIBUTE_MAP.put("givenName", "first");
|
||||
ATTRIBUTE_MAP.put("initials", "initials");
|
||||
ATTRIBUTE_MAP.put("last", "sn");
|
||||
ATTRIBUTE_MAP.put("sn", "last");
|
||||
ATTRIBUTE_MAP.put("street", "street");
|
||||
ATTRIBUTE_MAP.put("state", "st");
|
||||
ATTRIBUTE_MAP.put("zip", "postalCode");
|
||||
ATTRIBUTE_MAP.put("country", "c");
|
||||
ATTRIBUTE_MAP.put("st", "state");
|
||||
ATTRIBUTE_MAP.put("postalCode", "zip");
|
||||
ATTRIBUTE_MAP.put("c", "country");
|
||||
ATTRIBUTE_MAP.put("departement", "department");
|
||||
ATTRIBUTE_MAP.put("mobile", "mobile");
|
||||
}
|
||||
|
||||
/**
|
||||
* LDAP to Exchange Criteria Map
|
||||
*/
|
||||
static final HashMap<String, String> CRITERIA_MAP = new HashMap<String, String>();
|
||||
static {
|
||||
// assume mail starts with firstname
|
||||
CRITERIA_MAP.put("mail", "FN");
|
||||
CRITERIA_MAP.put("displayname", "DN");
|
||||
CRITERIA_MAP.put("cn", "DN");
|
||||
CRITERIA_MAP.put("givenname", "FN");
|
||||
CRITERIA_MAP.put("sn", "LN");
|
||||
CRITERIA_MAP.put("title", "TL");
|
||||
CRITERIA_MAP.put("company", "CP");
|
||||
CRITERIA_MAP.put("o", "CP");
|
||||
CRITERIA_MAP.put("l", "OF");
|
||||
CRITERIA_MAP.put("department", "DP");
|
||||
}
|
||||
|
||||
// LDAP version
|
||||
static final int LDAP_VERSION2 = 0x02;
|
||||
static final int LDAP_VERSION3 = 0x03;
|
||||
@ -104,6 +125,11 @@ public class LdapConnection extends AbstractConnection {
|
||||
*/
|
||||
protected BerEncoder responseBer = new BerEncoder();
|
||||
|
||||
/**
|
||||
* Current LDAP version (used for String encoding)
|
||||
*/
|
||||
int ldapVersion = LDAP_VERSION3;
|
||||
|
||||
// Initialize the streams and start the thread
|
||||
public LdapConnection(String name, Socket clientSocket) {
|
||||
super(name + "-" + clientSocket.getPort(), clientSocket);
|
||||
@ -116,16 +142,18 @@ public class LdapConnection extends AbstractConnection {
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isLdapV3() {
|
||||
return ldapVersion == LDAP_VERSION3;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
byte inbuf[] = new byte[2048]; // Buffer for reading incoming bytes
|
||||
int currentMessageId = 0; // Message id of incoming response
|
||||
int bytesread; // Number of bytes in inbuf
|
||||
int bytesleft; // Number of bytes that need to read for completing resp
|
||||
int br; // Temp; number of bytes read from stream
|
||||
int offset; // Offset of where to store bytes in inbuf
|
||||
int seqlen; // Length of ASN sequence
|
||||
int seqlenlen; // Number of sequence length bytes
|
||||
int operation = 0;
|
||||
boolean eos; // End of stream
|
||||
BerDecoder reqBer; // Decoder for ASN.1 BER data from inbuf
|
||||
|
||||
@ -198,351 +226,258 @@ public class LdapConnection extends AbstractConnection {
|
||||
bytesleft -= bytesread;
|
||||
}
|
||||
|
||||
reqBer = new BerDecoder(inbuf, 0, offset);
|
||||
|
||||
reqBer.parseSeq(null);
|
||||
currentMessageId = reqBer.parseInt();
|
||||
operation = reqBer.parseSeq(null);
|
||||
|
||||
responseBer.reset();
|
||||
//Ber.dumpBER(System.out, "request\n", inbuf, 0, offset);
|
||||
|
||||
if (operation == LDAP_REQ_BIND) {
|
||||
int ldapVersion = reqBer.parseInt();
|
||||
String userName = reqBer.parseString(ldapVersion == LDAP_VERSION3);
|
||||
String password = reqBer.parseStringWithTag(Ber.ASN_CONTEXT, ldapVersion == LDAP_VERSION3, null);
|
||||
|
||||
if (userName.length() > 0 && password.length() > 0) {
|
||||
try {
|
||||
session = ExchangeSessionFactory.getInstance(userName, password);
|
||||
sendClient(currentMessageId, LDAP_REP_BIND, LDAP_SUCCESS, "");
|
||||
} catch (IOException e) {
|
||||
sendClient(currentMessageId, LDAP_REP_BIND, LDAP_INVALID_CREDENTIALS, "");
|
||||
}
|
||||
} else {
|
||||
// anonymous bind
|
||||
sendClient(currentMessageId, LDAP_REP_BIND, LDAP_SUCCESS, "");
|
||||
}
|
||||
|
||||
} else if (operation == LDAP_REQ_UNBIND) {
|
||||
if (session != null) {
|
||||
ExchangeSessionFactory.close(session);
|
||||
session = null;
|
||||
}
|
||||
} else if (operation == LDAP_REQ_SEARCH) {
|
||||
String dn = reqBer.parseString(true);
|
||||
int scope = reqBer.parseEnumeration();
|
||||
int deref = reqBer.parseEnumeration();
|
||||
int sizeLimit = reqBer.parseInt();
|
||||
if (sizeLimit > 100 || sizeLimit == 0) {
|
||||
sizeLimit = 100;
|
||||
}
|
||||
int timelimit = reqBer.parseInt();
|
||||
boolean attrsOnly = reqBer.parseBoolean();
|
||||
int size = 0;
|
||||
|
||||
if (scope == SCOPE_BASE_OBJECT) {
|
||||
if ("".equals(dn)) {
|
||||
size = 1;
|
||||
sendRootDSE(currentMessageId);
|
||||
}
|
||||
if (BASE_CONTEXT.equals(dn)) {
|
||||
size = 1;
|
||||
// root
|
||||
responseBer.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
|
||||
responseBer.encodeInt(currentMessageId);
|
||||
responseBer.beginSeq(LDAP_REP_SEARCH);
|
||||
|
||||
responseBer.encodeString(BASE_CONTEXT, true);
|
||||
responseBer.beginSeq(LBER_SEQUENCE);
|
||||
responseBer.beginSeq(LBER_SEQUENCE);
|
||||
responseBer.encodeString("description", true);
|
||||
responseBer.beginSeq(LBER_SET);
|
||||
responseBer.encodeString("people", true);
|
||||
responseBer.endSeq();
|
||||
responseBer.endSeq();
|
||||
responseBer.endSeq();
|
||||
|
||||
responseBer.endSeq();
|
||||
responseBer.endSeq();
|
||||
} else if (dn.startsWith("uid=") && session != null) {
|
||||
String uid = dn.substring(4, dn.indexOf(','));
|
||||
Map<String, Map<String, String>> persons = session.galFind("AN", uid);
|
||||
size = persons.size();
|
||||
// TODO refactor
|
||||
for (Map<String, String> person : persons.values()) {
|
||||
Map<String, String> ldapPerson = new HashMap<String, String>();
|
||||
|
||||
for (Map.Entry<String, String> entry : ATTRIBUTE_MAP.entrySet()) {
|
||||
String ldapAttribute = entry.getKey();
|
||||
String exchangeAttribute = entry.getValue();
|
||||
String value = person.get(exchangeAttribute);
|
||||
if (value != null) {
|
||||
ldapPerson.put(ldapAttribute, value);
|
||||
}
|
||||
}
|
||||
|
||||
responseBer.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
|
||||
responseBer.encodeInt(currentMessageId);
|
||||
responseBer.beginSeq(LDAP_REP_SEARCH);
|
||||
|
||||
responseBer.encodeString("uid=" + ldapPerson.get("uid") + ","+BASE_CONTEXT, true);
|
||||
responseBer.beginSeq(LBER_SEQUENCE);
|
||||
|
||||
for (Map.Entry<String, String> entry : ldapPerson.entrySet()) {
|
||||
responseBer.beginSeq(LBER_SEQUENCE);
|
||||
responseBer.encodeString(entry.getKey(), true);
|
||||
responseBer.beginSeq(LBER_SET);
|
||||
responseBer.encodeString(entry.getValue(), true);
|
||||
responseBer.endSeq();
|
||||
responseBer.endSeq();
|
||||
}
|
||||
responseBer.endSeq();
|
||||
|
||||
responseBer.endSeq();
|
||||
responseBer.endSeq();
|
||||
|
||||
}
|
||||
//end TODO
|
||||
}
|
||||
|
||||
} else if (BASE_CONTEXT.equals(dn) && session != null) {
|
||||
// filter
|
||||
Map<String, String> criteria = new HashMap<String, String>();
|
||||
try {
|
||||
int[] seqSize = new int[1];
|
||||
int ldapFilterType = reqBer.parseSeq(seqSize);
|
||||
int end = reqBer.getParsePosition() + seqSize[0];
|
||||
if (ldapFilterType == LDAP_FILTER_OR) {
|
||||
System.out.print("(|");
|
||||
while (reqBer.getParsePosition() < end && reqBer.bytesLeft() > 0) {
|
||||
int ldapFilterOperator = reqBer.parseSeq(null);
|
||||
if (ldapFilterOperator == LDAP_FILTER_SUBSTRINGS) {
|
||||
String attributeName = reqBer.parseString(true).toLowerCase();
|
||||
/*LBER_SEQUENCE*/
|
||||
reqBer.parseSeq(null);
|
||||
int ldapFilterMode = reqBer.peekByte();
|
||||
String value = reqBer.parseStringWithTag(ldapFilterMode, true, null);
|
||||
if (ldapFilterMode == LDAP_SUBSTRING_ANY) {
|
||||
System.out.print("(" + attributeName + "=*" + value + "*)");
|
||||
} else if (ldapFilterMode == LDAP_SUBSTRING_INITIAL) {
|
||||
System.out.print("(" + attributeName + "=" + value + "*)");
|
||||
} else if (ldapFilterMode == LDAP_SUBSTRING_FINAL) {
|
||||
System.out.print("(" + attributeName + "=*" + value + ")");
|
||||
}
|
||||
criteria.put(attributeName, value);
|
||||
}
|
||||
}
|
||||
System.out.println(")");
|
||||
// simple filter
|
||||
} else if (ldapFilterType == LDAP_FILTER_SUBSTRINGS) {
|
||||
// TODO refactor
|
||||
String attributeName = reqBer.parseString(true).toLowerCase();
|
||||
/*LBER_SEQUENCE*/
|
||||
reqBer.parseSeq(null);
|
||||
int ldapFilterMode = reqBer.peekByte();
|
||||
String value = reqBer.parseStringWithTag(ldapFilterMode, true, null);
|
||||
if (ldapFilterMode == LDAP_SUBSTRING_ANY) {
|
||||
System.out.print("(" + attributeName + "=*" + value + "*)");
|
||||
} else if (ldapFilterMode == LDAP_SUBSTRING_INITIAL) {
|
||||
System.out.print("(" + attributeName + "=" + value + "*)");
|
||||
} else if (ldapFilterMode == LDAP_SUBSTRING_FINAL) {
|
||||
System.out.print("(" + attributeName + "=*" + value + ")");
|
||||
}
|
||||
criteria.put(attributeName, value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// unsupported filter
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
Map<String, Map<String, String>> persons = new HashMap<String, Map<String, String>>();
|
||||
if (criteria.size() > 0) {
|
||||
if (criteria.containsKey("displayname")) {
|
||||
for (Map<String, String> person : session.galFind("DN", criteria.get("displayname")).values()) {
|
||||
persons.put(person.get("AN"), person);
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (criteria.containsKey("cn")) {
|
||||
for (Map<String, String> person : session.galFind("DN", criteria.get("cn")).values()) {
|
||||
persons.put(person.get("AN"), person);
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (criteria.containsKey("givenname") && persons.size() < sizeLimit) {
|
||||
for (Map<String, String> person : session.galFind("FN", criteria.get("givenname")).values()) {
|
||||
persons.put(person.get("AN"), person);
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (criteria.containsKey("sn") && persons.size() < sizeLimit) {
|
||||
for (Map<String, String> person : session.galFind("LN", criteria.get("sn")).values()) {
|
||||
persons.put(person.get("AN"), person);
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (criteria.containsKey("title") && persons.size() < sizeLimit) {
|
||||
for (Map<String, String> person : session.galFind("TL", criteria.get("title")).values()) {
|
||||
persons.put(person.get("AN"), person);
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (criteria.containsKey("company") && persons.size() < sizeLimit) {
|
||||
for (Map<String, String> person : session.galFind("CP", criteria.get("company")).values()) {
|
||||
persons.put(person.get("AN"), person);
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (criteria.containsKey("o") && persons.size() < sizeLimit) {
|
||||
for (Map<String, String> person : session.galFind("CP", criteria.get("o")).values()) {
|
||||
persons.put(person.get("AN"), person);
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (criteria.containsKey("department") && persons.size() < sizeLimit) {
|
||||
for (Map<String, String> person : session.galFind("DP", criteria.get("department")).values()) {
|
||||
persons.put(person.get("AN"), person);
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (criteria.containsKey("l") && persons.size() < sizeLimit) {
|
||||
for (Map<String, String> person : session.galFind("OF", criteria.get("l")).values()) {
|
||||
persons.put(person.get("AN"), person);
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (criteria.containsKey("l") && persons.size() < sizeLimit) {
|
||||
for (Map<String, String> person : session.galFind("OF", criteria.get("l")).values()) {
|
||||
persons.put(person.get("AN"), person);
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// full list
|
||||
for (char c = 'A'; c < 'Z'; c++) {
|
||||
if (persons.size() < sizeLimit) {
|
||||
for (Map<String, String> person : session.galFind("AN", String.valueOf(c)).values()) {
|
||||
persons.put(person.get("AN"), person);
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size = persons.size();
|
||||
for (Map<String, String> person : persons.values()) {
|
||||
|
||||
|
||||
Map<String, String> ldapPerson = new HashMap<String, String>();
|
||||
for (Map.Entry<String, String> entry : person.entrySet()) {
|
||||
String ldapAttribute = ATTRIBUTE_MAP.get(entry.getKey());
|
||||
if (ldapAttribute != null) {
|
||||
ldapPerson.put(ldapAttribute, entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
responseBer.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
|
||||
responseBer.encodeInt(currentMessageId);
|
||||
responseBer.beginSeq(LDAP_REP_SEARCH);
|
||||
|
||||
responseBer.encodeString("uid=" + ldapPerson.get("uid") + ","+BASE_CONTEXT, true);
|
||||
responseBer.beginSeq(LBER_SEQUENCE);
|
||||
|
||||
for (Map.Entry<String, String> entry : ldapPerson.entrySet()) {
|
||||
responseBer.beginSeq(LBER_SEQUENCE);
|
||||
responseBer.encodeString(entry.getKey(), true);
|
||||
responseBer.beginSeq(LBER_SET);
|
||||
responseBer.encodeString(entry.getValue(), true);
|
||||
responseBer.endSeq();
|
||||
responseBer.endSeq();
|
||||
}
|
||||
responseBer.endSeq();
|
||||
|
||||
responseBer.endSeq();
|
||||
responseBer.endSeq();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sendResponse();
|
||||
if (size == sizeLimit) {
|
||||
sendClient(currentMessageId, LDAP_REP_RESULT, LDAP_SIZE_LIMIT_EXCEEDED, "");
|
||||
} else {
|
||||
sendClient(currentMessageId, LDAP_REP_RESULT, LDAP_SUCCESS, "");
|
||||
}
|
||||
} else {
|
||||
sendClient(currentMessageId, LDAP_REP_RESULT, LDAP_OTHER, "Unsupported operation");
|
||||
}
|
||||
handleRequest(new BerDecoder(inbuf, 0, offset));
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
DavGatewayTray.debug("Closing connection on timeout");
|
||||
} catch (IOException e) {
|
||||
DavGatewayTray.error(e);
|
||||
try {
|
||||
sendErr(currentMessageId, LDAP_REP_RESULT, e);
|
||||
} catch (IOException e2) {
|
||||
DavGatewayTray.debug("Exception sending error to client", e2);
|
||||
}
|
||||
} finally {
|
||||
close();
|
||||
}
|
||||
DavGatewayTray.resetIcon();
|
||||
}
|
||||
|
||||
protected void handleRequest(BerDecoder reqBer) throws IOException {
|
||||
int currentMessageId = 0;
|
||||
try {
|
||||
reqBer.parseSeq(null);
|
||||
currentMessageId = reqBer.parseInt();
|
||||
int requestOperation = reqBer.parseSeq(null);
|
||||
|
||||
//Ber.dumpBER(System.out, "request\n", inbuf, 0, offset);
|
||||
|
||||
if (requestOperation == LDAP_REQ_BIND) {
|
||||
int ldapVersion = reqBer.parseInt();
|
||||
String userName = reqBer.parseString(ldapVersion == LDAP_VERSION3);
|
||||
String password = reqBer.parseStringWithTag(Ber.ASN_CONTEXT, ldapVersion == LDAP_VERSION3, null);
|
||||
|
||||
if (userName.length() > 0 && password.length() > 0) {
|
||||
DavGatewayTray.debug("LDAP_REQ_BIND "+userName);
|
||||
try {
|
||||
session = ExchangeSessionFactory.getInstance(userName, password);
|
||||
sendClient(currentMessageId, LDAP_REP_BIND, LDAP_SUCCESS, "");
|
||||
} catch (IOException e) {
|
||||
sendClient(currentMessageId, LDAP_REP_BIND, LDAP_INVALID_CREDENTIALS, "");
|
||||
}
|
||||
} else {
|
||||
DavGatewayTray.debug("LDAP_REQ_BIND anonymous"+userName);
|
||||
// anonymous bind
|
||||
sendClient(currentMessageId, LDAP_REP_BIND, LDAP_SUCCESS, "");
|
||||
}
|
||||
|
||||
} else if (requestOperation == LDAP_REQ_UNBIND) {
|
||||
DavGatewayTray.debug("LDAP_REQ_UNBIND");
|
||||
if (session != null) {
|
||||
ExchangeSessionFactory.close(session);
|
||||
session = null;
|
||||
}
|
||||
} else if (requestOperation == LDAP_REQ_SEARCH) {
|
||||
String dn = reqBer.parseString(isLdapV3());
|
||||
int scope = reqBer.parseEnumeration();
|
||||
/*int deref =*/ reqBer.parseEnumeration();
|
||||
int sizeLimit = reqBer.parseInt();
|
||||
if (sizeLimit > 100 || sizeLimit == 0) {
|
||||
sizeLimit = 100;
|
||||
}
|
||||
/* int timelimit = */reqBer.parseInt();
|
||||
/* boolean attrsOnly = */reqBer.parseBoolean();
|
||||
int size = 0;
|
||||
DavGatewayTray.debug("LDAP_REQ_SEARCH base="+dn+" scope: "+scope+" sizelimit: "+sizeLimit);
|
||||
|
||||
if (scope == SCOPE_BASE_OBJECT) {
|
||||
if ("".equals(dn)) {
|
||||
size = 1;
|
||||
sendRootDSE(currentMessageId);
|
||||
}
|
||||
if (BASE_CONTEXT.equals(dn)) {
|
||||
size = 1;
|
||||
// root
|
||||
sendBaseContext(currentMessageId);
|
||||
} else if (dn.startsWith("uid=") && dn.indexOf(',') > 0 && session != null) {
|
||||
// single user request
|
||||
String uid = dn.substring("uid=".length(), dn.indexOf(','));
|
||||
Map<String, Map<String, String>> persons = session.galFind("AN", uid);
|
||||
size = persons.size();
|
||||
sendPersons(currentMessageId, persons);
|
||||
}
|
||||
|
||||
} else if (BASE_CONTEXT.equalsIgnoreCase(dn) && session != null) {
|
||||
|
||||
Map<String, String> criteria = parseFilter(reqBer);
|
||||
|
||||
Map<String, Map<String, String>> persons = new HashMap<String, Map<String, String>>();
|
||||
if ("*".equals(criteria.get("objectclass"))) {
|
||||
// full search
|
||||
for (char c = 'A'; c < 'Z'; c++) {
|
||||
if (persons.size() < sizeLimit) {
|
||||
for (Map<String, String> person : session.galFind("AN", String.valueOf(c)).values()) {
|
||||
persons.put(person.get("AN"), person);
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Map.Entry<String, String> entry : criteria.entrySet()) {
|
||||
if (persons.size() < sizeLimit) {
|
||||
for (Map<String, String> person : session.galFind(entry.getKey(), entry.getValue()).values()) {
|
||||
persons.put(person.get("AN"), person);
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (persons.size() == sizeLimit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size = persons.size();
|
||||
DavGatewayTray.debug("LDAP_REQ_SEARCH found "+size+" results");
|
||||
sendPersons(currentMessageId, persons);
|
||||
DavGatewayTray.debug("LDAP_REQ_SEARCH end");
|
||||
}
|
||||
|
||||
if (size == sizeLimit) {
|
||||
sendClient(currentMessageId, LDAP_REP_RESULT, LDAP_SIZE_LIMIT_EXCEEDED, "");
|
||||
} else {
|
||||
sendClient(currentMessageId, LDAP_REP_RESULT, LDAP_SUCCESS, "");
|
||||
}
|
||||
} else {
|
||||
DavGatewayTray.debug("Unsupported operation: "+requestOperation);
|
||||
sendClient(currentMessageId, LDAP_REP_RESULT, LDAP_OTHER, "Unsupported operation");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
sendErr(currentMessageId, LDAP_REP_RESULT, e);
|
||||
} catch (IOException e2) {
|
||||
DavGatewayTray.debug("Exception sending error to client", e2);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
protected Map<String, String> parseFilter(BerDecoder reqBer) throws IOException {
|
||||
Map<String, String> criteria = new HashMap<String, String>();
|
||||
if (reqBer.peekByte() == LDAP_FILTER_PRESENT) {
|
||||
String attributeName = reqBer.parseStringWithTag(LDAP_FILTER_PRESENT, isLdapV3(), null).toLowerCase();
|
||||
if ("objectclass".equals(attributeName)) {
|
||||
criteria.put(attributeName, "*");
|
||||
} else {
|
||||
DavGatewayTray.warn("Unsupported filter");
|
||||
}
|
||||
} else {
|
||||
int[] seqSize = new int[1];
|
||||
int ldapFilterType = reqBer.parseSeq(seqSize);
|
||||
int end = reqBer.getParsePosition() + seqSize[0];
|
||||
if (ldapFilterType == LDAP_FILTER_OR) {
|
||||
while (reqBer.getParsePosition() < end && reqBer.bytesLeft() > 0) {
|
||||
int ldapFilterOperator = reqBer.parseSeq(null);
|
||||
if (ldapFilterOperator == LDAP_FILTER_SUBSTRINGS) {
|
||||
parseSimpleFilter(reqBer, criteria);
|
||||
}
|
||||
}
|
||||
// simple filter
|
||||
} else if (ldapFilterType == LDAP_FILTER_SUBSTRINGS) {
|
||||
parseSimpleFilter(reqBer, criteria);
|
||||
} else {
|
||||
DavGatewayTray.warn("Unsupported filter");
|
||||
}
|
||||
}
|
||||
return criteria;
|
||||
}
|
||||
|
||||
protected void parseSimpleFilter(BerDecoder reqBer, Map<String, String> criteria) throws IOException {
|
||||
String attributeName = reqBer.parseString(isLdapV3()).toLowerCase();
|
||||
/*LBER_SEQUENCE*/
|
||||
reqBer.parseSeq(null);
|
||||
int ldapFilterMode = reqBer.peekByte();
|
||||
String value = reqBer.parseStringWithTag(ldapFilterMode, isLdapV3(), null);
|
||||
String exchangeAttributeName = CRITERIA_MAP.get(attributeName);
|
||||
if (exchangeAttributeName != null) {
|
||||
criteria.put(exchangeAttributeName, value);
|
||||
} else {
|
||||
DavGatewayTray.warn("Unsupported filter attribute: " + attributeName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to LDAP attributes and send entry
|
||||
* @param currentMessageId current Message Id
|
||||
* @param persons persons Map
|
||||
* @throws IOException on error
|
||||
*/
|
||||
protected void sendPersons(int currentMessageId, Map<String, Map<String, String>> persons) throws IOException {
|
||||
for (Map<String, String> person : persons.values()) {
|
||||
// add detailed information, only if few results
|
||||
if (persons.size() <=10) {
|
||||
session.galLookup(person);
|
||||
}
|
||||
|
||||
Map<String, Object> ldapPerson = new HashMap<String, Object>();
|
||||
for (Map.Entry<String, String> entry : ATTRIBUTE_MAP.entrySet()) {
|
||||
String ldapAttribute = entry.getKey();
|
||||
String exchangeAttribute = entry.getValue();
|
||||
String value = person.get(exchangeAttribute);
|
||||
if (value != null) {
|
||||
ldapPerson.put(ldapAttribute, value);
|
||||
}
|
||||
}
|
||||
|
||||
sendEntry(currentMessageId, "uid=" + ldapPerson.get("uid") + "," + BASE_CONTEXT, ldapPerson);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Send Root DSE
|
||||
* @throws IOException
|
||||
* @param currentMessageId current message id
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public void sendRootDSE(int currentMessageId) throws IOException {
|
||||
Map<String,Object> attributes = new HashMap<String,Object>();
|
||||
protected void sendRootDSE(int currentMessageId) throws IOException {
|
||||
Map<String, Object> attributes = new HashMap<String, Object>();
|
||||
attributes.put("objectClass", "top");
|
||||
attributes.put("namingContexts", BASE_CONTEXT);
|
||||
sendEntry(currentMessageId, "Root DSE", attributes);
|
||||
}
|
||||
|
||||
public void sendEntry(int currentMessageId, String dn, Map<String,Object> attributes) throws IOException {
|
||||
/**
|
||||
* Send Base Context
|
||||
* @param currentMessageId current message id
|
||||
* @throws IOException on error
|
||||
*/
|
||||
protected void sendBaseContext(int currentMessageId) throws IOException {
|
||||
List<String> objectClasses = new ArrayList<String>();
|
||||
objectClasses.add("top");
|
||||
objectClasses.add("organizationalUnit");
|
||||
Map<String, Object> attributes = new HashMap<String, Object>();
|
||||
attributes.put("objectClass", objectClasses);
|
||||
attributes.put("description", "DavMail Gateway LDAP for " + Settings.getProperty("davmail.url"));
|
||||
sendEntry(currentMessageId, BASE_CONTEXT, attributes);
|
||||
}
|
||||
|
||||
protected void sendEntry(int currentMessageId, String dn, Map<String,Object> attributes) throws IOException {
|
||||
responseBer.reset();
|
||||
responseBer.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
|
||||
responseBer.encodeInt(currentMessageId);
|
||||
responseBer.beginSeq(LDAP_REP_SEARCH);
|
||||
responseBer.encodeString(dn, true);
|
||||
responseBer.encodeString(dn, isLdapV3());
|
||||
responseBer.beginSeq(LBER_SEQUENCE);
|
||||
for (Map.Entry<String,Object> entry:attributes.entrySet()) {
|
||||
responseBer.beginSeq(LBER_SEQUENCE);
|
||||
responseBer.encodeString(entry.getKey(), true);
|
||||
responseBer.encodeString(entry.getKey(), isLdapV3());
|
||||
responseBer.beginSeq(LBER_SET);
|
||||
Object values = entry.getValue();
|
||||
if (values instanceof String) {
|
||||
responseBer.encodeString((String)values, true);
|
||||
responseBer.encodeString((String)values, isLdapV3());
|
||||
} else if (values instanceof List) {
|
||||
for (Object value: (List)values) {
|
||||
responseBer.encodeString((String) value, true);
|
||||
responseBer.encodeString((String) value, isLdapV3());
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
@ -556,7 +491,7 @@ public class LdapConnection extends AbstractConnection {
|
||||
sendResponse();
|
||||
}
|
||||
|
||||
public void sendErr(int currentMessageId, int responseOperation, Exception e) throws IOException {
|
||||
protected void sendErr(int currentMessageId, int responseOperation, Exception e) throws IOException {
|
||||
String message = e.getMessage();
|
||||
if (message == null) {
|
||||
message = e.toString();
|
||||
@ -564,7 +499,7 @@ public class LdapConnection extends AbstractConnection {
|
||||
sendClient(currentMessageId, responseOperation, LDAP_OTHER, message);
|
||||
}
|
||||
|
||||
public void sendClient(int currentMessageId, int responseOperation, int status, String message) throws IOException {
|
||||
protected void sendClient(int currentMessageId, int responseOperation, int status, String message) throws IOException {
|
||||
responseBer.reset();
|
||||
|
||||
responseBer.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
|
||||
@ -572,15 +507,15 @@ public class LdapConnection extends AbstractConnection {
|
||||
responseBer.beginSeq(responseOperation);
|
||||
responseBer.encodeInt(status, LBER_ENUMERATED);
|
||||
// dn
|
||||
responseBer.encodeString("", true);
|
||||
responseBer.encodeString("", isLdapV3());
|
||||
// error message
|
||||
responseBer.encodeString(message, true);
|
||||
responseBer.encodeString(message, isLdapV3());
|
||||
responseBer.endSeq();
|
||||
responseBer.endSeq();
|
||||
sendResponse();
|
||||
}
|
||||
|
||||
public void sendResponse() throws IOException {
|
||||
protected void sendResponse() throws IOException {
|
||||
//Ber.dumpBER(System.out, ">\n", responseBer.getBuf(), 0, responseBer.getDataLen());
|
||||
os.write(responseBer.getBuf(), 0, responseBer.getDataLen());
|
||||
os.flush();
|
||||
|
Loading…
Reference in New Issue
Block a user