Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for retrieving user certificates #353

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/java/davmail/exchange/ExchangeSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -2020,6 +2020,9 @@ public String getBody() {
writer.writeLine("PHOTO;TYPE=" + contactPhoto.contentType + ";ENCODING=BASE64:");
writer.writeLine(contactPhoto.content, true);
}

writer.appendProperty("KEY1;X509;ENCODING=BASE64", get("msexchangecertificate"));
writer.appendProperty("KEY2;X509;ENCODING=BASE64", get("usersmimecertificate"));

writer.endCard();
return writer.toString();
Expand Down Expand Up @@ -2798,6 +2801,10 @@ protected ItemResult createOrUpdateContact(String folderPath, String itemName, S
} else if ("PHOTO".equals(property.getKey())) {
properties.put("photo", property.getValue());
properties.put("haspicture", "true");
} else if ("KEY1".equals(property.getKey())) {
properties.put("msexchangecertificate", property.getValue());
} else if ("KEY2".equals(property.getKey())) {
properties.put("usersmimecertificate", property.getValue());
}
}
LOGGER.debug("Create or update contact " + itemName + ": " + properties);
Expand Down Expand Up @@ -3012,6 +3019,8 @@ public String getAlias() {
CONTACT_ATTRIBUTES.add("private");
CONTACT_ATTRIBUTES.add("sensitivity");
CONTACT_ATTRIBUTES.add("fburl");
CONTACT_ATTRIBUTES.add("msexchangecertificate");
CONTACT_ATTRIBUTES.add("usersmimecertificate");
}

protected static final Set<String> DISTRIBUTION_LIST_ATTRIBUTES = new HashSet<>();
Expand Down
34 changes: 34 additions & 0 deletions src/java/davmail/exchange/ews/ContactDataShape.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
* Copyright (C) 2010 Mickael Guessant
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package davmail.exchange.ews;

/**
* ResolveNames contact data shape.
*/
@SuppressWarnings({"UnusedDeclaration"})
public class ContactDataShape extends AttributeOption {
private ContactDataShape(String value) {
super("ContactDataShape", value);
}

public static final ContactDataShape IdOnly = new ContactDataShape("IdOnly");
public static final ContactDataShape Default = new ContactDataShape("Default");
public static final ContactDataShape AllProperties = new ContactDataShape("AllProperties");

}
2 changes: 2 additions & 0 deletions src/java/davmail/exchange/ews/EwsExchangeSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -2975,6 +2975,8 @@ protected void internalExecuteMethod(EWSMethod ewsMethod) throws IOException {

GALFIND_ATTRIBUTE_MAP.put("homePhone", "HomePhone");
GALFIND_ATTRIBUTE_MAP.put("pager", "Pager");
GALFIND_ATTRIBUTE_MAP.put("msexchangecertificate", "MSExchangeCertificate");
GALFIND_ATTRIBUTE_MAP.put("usersmimecertificate", "UserSMIMECertificate");
}

protected static final HashSet<String> IGNORE_ATTRIBUTE_SET = new HashSet<>();
Expand Down
3 changes: 3 additions & 0 deletions src/java/davmail/exchange/ews/Field.java
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@ private Field() {
// attachments
FIELD_MAP.put("attachments", new UnindexedFieldURI("item:Attachments"));

// user certificate
FIELD_MAP.put("msexchangecertificate", new UnindexedFieldURI("contacts:MSExchangeCertificate"));
FIELD_MAP.put("usersmimecertificate", new UnindexedFieldURI("contacts:UserSMIMECertificate"));
}

/**
Expand Down
53 changes: 53 additions & 0 deletions src/java/davmail/exchange/ews/ResolveNamesMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public ResolveNamesMethod(String value) {
super("Contact", "ResolveNames", "ResolutionSet");
addMethodOption(SearchScope.ActiveDirectory);
addMethodOption(RETURN_FULL_CONTACT_DATA);
addMethodOption(ContactDataShape.AllProperties);
unresolvedEntry = new ElementOption("m:UnresolvedEntry", value);
}

Expand Down Expand Up @@ -88,6 +89,27 @@ protected void handleContact(XMLStreamReader reader, Item responseItem) throws X
handlePhysicalAddresses(reader, responseItem);
} else if ("PhoneNumbers".equals(tagLocalName)) {
handlePhoneNumbers(reader, responseItem);
} else if ("MSExchangeCertificate".equals(tagLocalName)
|| "UserSMIMECertificate".equals(tagLocalName)) {
handleUserCertificate(reader, responseItem, tagLocalName);
} else if ("ManagerMailbox".equals(tagLocalName)
|| "Attachments".equals(tagLocalName)
|| "Photo".equals(tagLocalName)
|| "Notes".equals(tagLocalName)
|| "HasPicture".equals(tagLocalName)
|| "DirectoryId".equals(tagLocalName)
|| "Alias".equals(tagLocalName)
|| "Categories".equals(tagLocalName)
|| "InternetMessageHeaders".equals(tagLocalName)
|| "ResponseObjects".equals(tagLocalName)
|| "ExtendedProperty".equals(tagLocalName)
|| "EffectiveRights".equals(tagLocalName)
|| "CompleteName".equals(tagLocalName)
|| "Children".equals(tagLocalName)
|| "Companies".equals(tagLocalName)
|| "ImAddresses".equals(tagLocalName)
|| "DirectReports".equals(tagLocalName)) {
skipTag(reader, tagLocalName);
} else {
responseItem.put(tagLocalName, XMLStreamUtil.getElementText(reader));
}
Expand Down Expand Up @@ -133,6 +155,37 @@ protected void handlePhoneNumbers(XMLStreamReader reader, Item responseItem) thr
}
}

protected void handleUserCertificate(XMLStreamReader reader, Item responseItem, String contextTagLocalName) throws XMLStreamException {
boolean firstValueRead = false;
String certificate = "";
while (reader.hasNext() && !XMLStreamUtil.isEndTag(reader, contextTagLocalName)) {
reader.next();
if (XMLStreamUtil.isStartTag(reader)) {
String tagLocalName = reader.getLocalName();
if ("Base64Binary".equals(tagLocalName)) {
String value = reader.getElementText();
if ((value != null) && !value.isEmpty()) {
if (!firstValueRead) {
// Only first certificate value will be read
certificate = value;
singe marked this conversation as resolved.
Show resolved Hide resolved
} else {
LOGGER.debug("ResolveNames multiple certificates found, tagLocaleName="
+ contextTagLocalName + " Certificate [" + value + "] ignored");
}
}
}
}
}
responseItem.put(contextTagLocalName, certificate);
}

protected void skipTag(XMLStreamReader reader, String tagLocalName) throws XMLStreamException {
LOGGER.debug("ResolveNames tag parsing skipped. tagLocalName=" + tagLocalName);
while (reader.hasNext() && !XMLStreamUtil.isEndTag(reader, tagLocalName)) {
reader.next();
}
}

@Override
protected void handleEmailAddresses(XMLStreamReader reader, Item responseItem) throws XMLStreamException {
while (reader.hasNext() && !XMLStreamUtil.isEndTag(reader, "EmailAddresses")) {
Expand Down
17 changes: 17 additions & 0 deletions src/java/davmail/ldap/LdapConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import davmail.exchange.ExchangeSessionFactory;
import davmail.exchange.dav.DavExchangeSession;
import davmail.ui.tray.DavGatewayTray;
import davmail.util.IOUtil;
import org.apache.log4j.Logger;

import javax.naming.InvalidNameException;
Expand Down Expand Up @@ -122,6 +123,8 @@ public class LdapConnection extends AbstractConnection {
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("homeStreet", "mozillahomestreet");
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("businesshomepage", "mozillaworkurl");
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("nickname", "mozillanickname");
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("msexchangecertificate", "msexchangecertificate;binary");
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("usersmimecertificate", "usersmimecertificate;binary");
}

/**
Expand Down Expand Up @@ -287,6 +290,10 @@ public class LdapConnection extends AbstractConnection {

// iCal search attribute
LDAP_TO_CONTACT_ATTRIBUTE_MAP.put("apple-serviceslocator", "apple-serviceslocator");

LDAP_TO_CONTACT_ATTRIBUTE_MAP.put("msexchangecertificate;binary", "msexchangecertificate");
LDAP_TO_CONTACT_ATTRIBUTE_MAP.put("usersmimecertificate;binary", "usersmimecertificate");

}

/**
Expand Down Expand Up @@ -967,6 +974,8 @@ protected void sendEntry(int currentMessageId, String dn, Map<String, Object> at
for (Object value : (Iterable) values) {
responseBer.encodeString((String) value, isLdapV3());
}
} else if (values instanceof byte[]) {
responseBer.encodeOctetString((byte[])values, BerEncoder.ASN_OCTET_STR);
} else {
throw new DavMailException("EXCEPTION_UNSUPPORTED_VALUE", values);
}
Expand Down Expand Up @@ -1688,6 +1697,14 @@ protected void sendPersons(int currentMessageId, String baseContext, Map<String,
ldapPerson.put("apple-generateduid", ldapPerson.get("uid"));
}
}
if (ldapPerson.containsKey("msexchangecertificate;binary")) {
String certificate = (String) ldapPerson.get("msexchangecertificate;binary");
ldapPerson.put("msexchangecertificate;binary", IOUtil.decodeBase64(certificate));
}
if (ldapPerson.containsKey("usersmimecertificate;binary")) {
String certificate = (String) ldapPerson.get("usersmimecertificate;binary");
ldapPerson.put("usersmimecertificate;binary", IOUtil.decodeBase64(certificate));
}

// iCal: replace current user alias with login name
if (session.getAlias().equals(ldapPerson.get("uid"))) {
Expand Down