diff options
Diffstat (limited to 'spss/server/serverlib/src')
-rw-r--r-- | spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/service/CertificateProviderServlet.java | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/service/CertificateProviderServlet.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/service/CertificateProviderServlet.java new file mode 100644 index 000000000..c8a0f68bf --- /dev/null +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/service/CertificateProviderServlet.java @@ -0,0 +1,178 @@ +package at.gv.egovernment.moa.spss.server.service; + +import iaik.server.modules.keys.KeyEntryID; +import iaik.server.modules.keys.KeyModule; +import iaik.server.modules.keys.KeyModuleFactory; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.Principal; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.spss.server.config.ConfigurationException; +import at.gv.egovernment.moa.spss.server.config.ConfigurationProvider; +import at.gv.egovernment.moa.spss.server.config.KeyGroupEntry; +import at.gv.egovernment.moa.spss.server.logging.TransactionId; +import at.gv.egovernment.moa.spss.server.transaction.TransactionIDGenerator; + +/** + * + * @author Andreas Fitzek + * @version $Id$ + */ +public class CertificateProviderServlet extends HttpServlet { + + /** + * + */ + private static final long serialVersionUID = -6907582473072190122L; + + /** The property name for accessing the X509 client certificate chain. */ + private static final String X509_CERTIFICATE_PROPERTY = "javax.servlet.request.X509Certificate"; + + public static final String PARAM_KEYID = "id"; + + /** + * Build the set of <code>KeyEntryID</code>s available to the given + * <code>keyGroupID</code>. + * + * @param keyGroupID + * The keygroup ID for which the available keys should be + * returned. + * @return The <code>Set</code> of <code>KeyEntryID</code>s identifying the + * available keys. + * @throws ConfigurationException + */ + private Set buildKeySet(String keyGroupID, X509Certificate cert, KeyModule module) + throws ConfigurationException { + ConfigurationProvider config = ConfigurationProvider.getInstance(); + Set keyGroupEntries; + + // get the KeyGroup entries from the configuration + if (cert != null) { + Principal issuer = cert.getIssuerDN(); + BigInteger serialNumber = cert.getSerialNumber(); + + keyGroupEntries = config.getKeyGroupEntries(issuer, serialNumber, + keyGroupID); + } else { + keyGroupEntries = config.getKeyGroupEntries(null, null, keyGroupID); + } + + // map the KeyGroup entries to a set of KeyEntryIDs + if (keyGroupEntries == null) { + return null; + } else if (keyGroupEntries.size() == 0) { + return Collections.EMPTY_SET; + } else { + + Set keyEntryIDs = module.getPrivateKeyEntryIDs(); + Set keySet = new HashSet(); + Iterator iter; + + // filter out the keys that do not exist in the IAIK configuration + // by walking through the key entries and checking if the exist in + // the + // keyGroupEntries + for (iter = keyEntryIDs.iterator(); iter.hasNext();) { + KeyEntryID entryID = (KeyEntryID) iter.next(); + KeyGroupEntry entry = new KeyGroupEntry(entryID.getModuleID(), + entryID.getCertificateIssuer(), + entryID.getCertificateSerialNumber()); + if (keyGroupEntries.contains(entry)) { + keySet.add(entryID); + } + } + return keySet; + } + } + + private X509Certificate getClientCertificate(HttpServletRequest request) { + X509Certificate[] clientCert = (X509Certificate[]) request + .getAttribute(X509_CERTIFICATE_PROPERTY); + if(clientCert != null) { + return clientCert[0]; + } + return null; + } + + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + try { + X509Certificate cert = getClientCertificate(request); + String keyId = request.getParameter(PARAM_KEYID); + + if(keyId == null) { + Logger.warn(PARAM_KEYID + " not provided in Request. Returning: " + HttpServletResponse.SC_BAD_REQUEST); + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + String transactionId = TransactionIDGenerator.nextID(); + + KeyModule module = KeyModuleFactory.getInstance(new TransactionId( + transactionId)); + + Set keySet = buildKeySet(keyId, cert, module); + + if(keySet == null || keySet.isEmpty()) { + Logger.warn("No keys available for Key Identifier " + keyId + " and given authentication."); + response.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + + + if(keySet.size() != 1) { + Logger.warn("Too many keys available for Key Identifier " + keyId + " and given authentication."); + response.sendError(HttpServletResponse.SC_CONFLICT); + return; + } + + Iterator iter; + + // filter out the keys that do not exist in the IAIK configuration + // by walking through the key entries and checking if the exist in + // the + // keyGroupEntries + for (iter = keySet.iterator(); iter.hasNext();) { + KeyEntryID entryID = (KeyEntryID) iter.next(); + + List certChain = module.getPrivateKeyEntry(entryID).getCertificateChain(); + + if(certChain != null && !certChain.isEmpty()) { + Logger.trace("Returning Certificate!"); + Certificate keyCert = ((Certificate)certChain.get(0)); + byte[] certData = keyCert.getEncoded(); + response.setStatus(HttpServletResponse.SC_OK); + response.setContentType("application/pkix-cert"); + response.setHeader("Content-disposition","attachment; filename=\"" + keyId + ".cer\""); + response.getOutputStream().write(certData); + response.getOutputStream().close(); + return; + } + + break; + } + + // No Certificate could be found! + Logger.warn("Failed to find keys available for Key Identifier " + keyId + " and given authentication."); + response.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } catch(Throwable e) { + Logger.error("Unhandled Exception when providing certificate", e); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } +} |