/** * Copyright 2006 by Know-Center, Graz, Austria * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a * joint initiative of the Federal Chancellery Austria and Graz University of * Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. */ package at.knowcenter.wag.egov.egiz.ldap.client; import iaik.x509.X509Certificate; import iaik.x509.net.ldap.LdapURLConnection; import java.io.IOException; import java.math.BigInteger; import java.net.MalformedURLException; import java.net.URL; import org.apache.log4j.Logger; public final class LDAPClientImpl implements LDAPClient { // constants protected static final String DEFAULT_LDAP_ATTR_SERIAL_NUMBER = "eidCertificateSerialNumber"; private static final iaik.x509.net.ldap.Handler LDAP_HANDLER = new iaik.x509.net.ldap.Handler(); private static final long TIME_ON_BLACKLIST_IN_SECONDS = 300; // block failed urls for 5 min private static final int READ_TIMEOUT = 15; private static final int CONNECTION_TIMEOUT = 15; private Logger log = Logger.getLogger(getClass()); // fields private URL url; private String serialNumberAttrName; private long timeStampForBlackList; // constructors protected LDAPClientImpl() { this.setSerialNumberAttrName(DEFAULT_LDAP_ATTR_SERIAL_NUMBER); this.timeStampForBlackList = 0; } protected LDAPClientImpl(URL url) { this(); this.setUrl(url); } protected LDAPClientImpl(String urlString) throws LDAPException { this(); try { this.setUrl(new URL(null, urlString, LDAP_HANDLER)); } catch (MalformedURLException e) { throw new LDAPException(e); } } protected LDAPClientImpl(LDAPMapping ldapMapping) { this(); this.setUrl(ldapMapping.getLdapURL()); this.setSerialNumberAttrName(ldapMapping.getSerialNumberAttrName()); } // getter/setter /* * @see at.iaik.commons.ldap.LDAPClient#getUrl() */ public URL getUrl() { return this.url; } /* * @see at.iaik.commons.ldap.LDAPClient#setUrl(java.net.URL) */ public void setUrl(URL ldapURL) { if (ldapURL == null) { throw new NullPointerException("LDAP url must not be null."); } this.url = ldapURL; } /* * @see at.iaik.commons.ldap.LDAPClient#getSerialNumberAttrName() */ public String getSerialNumberAttrName() { return this.serialNumberAttrName; } /* * @see at.iaik.commons.ldap.LDAPClient#setSerialNumberAttrName(java.lang.String) */ public void setSerialNumberAttrName(String serialNumberAttrName) { if (serialNumberAttrName != null && serialNumberAttrName.length() == 0) { throw new IllegalArgumentException("Serial number attribute name must not be empty"); } this.serialNumberAttrName = serialNumberAttrName != null ? serialNumberAttrName : DEFAULT_LDAP_ATTR_SERIAL_NUMBER; } // service methods /* * @see at.iaik.commons.ldap.LDAPClient#retrieveCertificates(java.lang.String) */ public X509Certificate[] retrieveCertificates(String filter) throws LDAPException { if (filter == null) { throw new NullPointerException("Filter string must not be null."); } if (filter.length() == 0) { throw new IllegalArgumentException("Filter string must not be empty."); } X509Certificate[] certs = new X509Certificate[] { }; long now = System.currentTimeMillis(); if (this.timeStampForBlackList + TIME_ON_BLACKLIST_IN_SECONDS * 1000 >= now) { long remaining = TIME_ON_BLACKLIST_IN_SECONDS - ((now - this.timeStampForBlackList) / 1000); log.warn("LDAP connections to URL \"" + this.getUrl().toString() + "\" are blocked for " + remaining + " (" + TIME_ON_BLACKLIST_IN_SECONDS + ") seconds due to previous errors."); return certs; } LdapURLConnection ldapURLConnection = null; try { this.validateData(); ldapURLConnection = (LdapURLConnection) this.url.openConnection(); log.debug("Setting timeout for LDAPClient: connection timeout = " + CONNECTION_TIMEOUT + " seconds, read timeout = " + READ_TIMEOUT + " seconds."); ldapURLConnection.setReadTimeout(READ_TIMEOUT * 1000); ldapURLConnection.setConnectTimeout(CONNECTION_TIMEOUT * 1000); // search for end enity certificates ldapURLConnection.setRequestProperty( LdapURLConnection.RP_ATTRIBUTE_DESCRIPTION, LdapURLConnection.AD_USER_CERTIFICATE ); // search subtree ldapURLConnection.setRequestProperty( LdapURLConnection.RP_SEARCH_SCOPE, LdapURLConnection.SEARCH_SCOPE_SUBTREE ); //set filter ldapURLConnection.setRequestProperty( LdapURLConnection.RP_FILTER, filter ); // connect to the ldap server an read results log.debug("Connecting to \"" + this.url.toString() + "\"."); certs = (X509Certificate[]) ldapURLConnection.getContent(); log.debug("Result of LDAP query received (" + (certs != null ? certs.length : 0) + " result(s))."); } catch (IOException e) { this.timeStampForBlackList = System.currentTimeMillis(); log.warn("Unable to get certificate from \"" + this.getUrl().toString() + "\". LDAPClient is now blocking that URL for " + TIME_ON_BLACKLIST_IN_SECONDS + " seconds."); throw new LDAPException(e); } finally { if (ldapURLConnection != null) { ldapURLConnection.disconnect(); } } return certs; } /* * @see at.iaik.commons.ldap.LDAPClient#retrieveCertificate(java.math.BigInteger) */ public X509Certificate retrieveCertificate(BigInteger serialNumber) throws LDAPException { if (serialNumber == null) { throw new NullPointerException("Serial number must not be null"); } this.validateData(); X509Certificate[] certs = retrieveCertificates("(" + this.serialNumberAttrName + "=" + serialNumber + ")"); if (certs.length > 1) { throw new LDAPException("There was more than one certificate with serial number " + serialNumber + "."); } else if (certs.length == 0) { return null; } return certs[0]; } // misc public void validateData() throws LDAPException { if (this.url == null) { throw new LDAPException("LDAP URL must not be null."); } if (this.serialNumberAttrName == null || this.serialNumberAttrName.length() == 0) { throw new LDAPException("LDAP key for serial number is null or empty."); } } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("ldapURL = ").append(this.url); buffer.append(", serialNumberAttrName = ").append(this.serialNumberAttrName); return buffer.toString(); } }