/*
* Copyright 2012 Future Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.krakenapps.ca;
import java.io.IOException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Invalidate;
import org.apache.felix.ipojo.annotations.Requires;
import org.apache.felix.ipojo.annotations.Validate;
import org.krakenapps.ca.util.CrlBuilder;
import org.krakenapps.httpd.HttpContext;
import org.krakenapps.httpd.HttpService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Servlet for CRL distribution
*
* @author xeraph
*/
@Component(name = "ca-crl-servlet")
public class CrlServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private final Logger logger = LoggerFactory.getLogger(CrlServlet.class.getName());
@Requires
private HttpService httpd;
@Requires
private CertificateAuthorityService ca;
@Validate
public void start() {
HttpContext ctx = httpd.ensureContext("frodo");
ctx.addServlet("crl", this, "/ca/crl/*");
}
@Invalidate
public void stop() {
if (httpd != null) {
HttpContext ctx = httpd.ensureContext("frodo");
ctx.removeServlet("crl");
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String authorityName = req.getPathInfo().substring(1); // remove slash
if (logger.isDebugEnabled())
logger.debug("kraken ca: crl [{}] request from [{}, {}]",
new Object[] { authorityName, req.getRequestURI(), req.getRemoteAddr() });
CertificateAuthority authority = ca.getAuthority(authorityName);
if (authority == null) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "CRL does not exists for " + authorityName);
return;
}
X509Certificate caCert = authority.getRootCertificate().getCertificate();
RSAPrivateKey caKey = authority.getRootCertificate().getPrivateKey(authority.getRootKeyPassword());
List<RevokedCertificate> revokes = null;
String serial = req.getParameter("serial");
if (serial != null) {
RevokedCertificate rc = authority.getRevokedCertificate(serial);
if (rc == null)
revokes = new ArrayList<RevokedCertificate>();
else
revokes = Arrays.asList(rc);
} else
revokes = authority.getRevokedCertificates();
try {
byte[] b = CrlBuilder.getCrl(caCert, caKey, revokes);
resp.setStatus(HttpServletResponse.SC_OK);
resp.setHeader("Content-Type", "application/pkix-crl");
resp.setContentLength(b.length);
resp.getOutputStream().write(b);
} catch (Exception e) {
logger.error("kraken ca: cannot generate crl for " + authorityName, e);
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Cannot generate CRL for " + authorityName);
} finally {
resp.getOutputStream().close();
}
}
}