Skip to content

Commit

Permalink
Implement GET verb for /ca/v2/certs/<id> REST end-point
Browse files Browse the repository at this point in the history
This replicate the current behaviour imeplemented in
/ca/rest/certs/<id>.
  • Loading branch information
fmarco76 committed Dec 7, 2023
1 parent cc95f31 commit 0493625
Show file tree
Hide file tree
Showing 4 changed files with 291 additions and 1 deletion.
19 changes: 19 additions & 0 deletions base/ca/src/main/java/org/dogtagpki/server/ca/CAServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* @author Marco Fargetta <[email protected]>
*/
public class CAServlet extends HttpServlet {
public static final long serialVersionUID = 1L;


public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {
}

public void post(HttpServletRequest request, HttpServletResponse response) throws Exception {
}

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Expand All @@ -33,6 +39,19 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro
}
}

@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
post(request, response);

} catch (ServletException | IOException e) {
throw e;

} catch (Exception e) {
throw new ServletException(e);
}
}

public CAEngine getCAEngine() {
ServletContext servletContext = getServletContext();
return (CAEngine) servletContext.getAttribute("engine");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
//
// Copyright Red Hat, Inc.
//
// SPDX-License-Identifier: GPL-2.0-or-later
//
package org.dogtagpki.server.ca.v2;

import java.io.PrintWriter;
Expand All @@ -13,11 +18,15 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author Marco Fargetta <[email protected]>
*/
@WebServlet("/v2/info")
public class CAInfoServlet extends CAServlet {
private static final long serialVersionUID = 1L;
private static Logger logger = LoggerFactory.getLogger(CAInfoServlet.class);

@Override
public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpSession session = request.getSession();
logger.debug("CAInfoServlet.get(): session: " + session.getId());
Expand Down
261 changes: 261 additions & 0 deletions base/ca/src/main/java/org/dogtagpki/server/ca/v2/CertServlet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
//
// Copyright Red Hat, Inc.
//
// SPDX-License-Identifier: GPL-2.0-or-later
//
package org.dogtagpki.server.ca.v2;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.security.InvalidKeyException;
import java.security.Principal;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.dogtagpki.server.ca.CAEngine;
import org.dogtagpki.server.ca.CAServlet;
import org.dogtagpki.util.cert.CertUtil;
import org.mozilla.jss.netscape.security.pkcs.ContentInfo;
import org.mozilla.jss.netscape.security.pkcs.PKCS7;
import org.mozilla.jss.netscape.security.pkcs.SignerInfo;
import org.mozilla.jss.netscape.security.provider.RSAPublicKey;
import org.mozilla.jss.netscape.security.util.CertPrettyPrint;
import org.mozilla.jss.netscape.security.util.Utils;
import org.mozilla.jss.netscape.security.x509.AlgorithmId;
import org.mozilla.jss.netscape.security.x509.CRLExtensions;
import org.mozilla.jss.netscape.security.x509.CRLReasonExtension;
import org.mozilla.jss.netscape.security.x509.X509CertImpl;
import org.mozilla.jss.netscape.security.x509.X509ExtensionException;
import org.mozilla.jss.netscape.security.x509.X509Key;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.PKIException;
import com.netscape.certsrv.cert.CertData;
import com.netscape.certsrv.cert.CertDataInfo;
import com.netscape.certsrv.cert.CertDataInfos;
import com.netscape.certsrv.dbs.certdb.CertId;
import com.netscape.cmscore.dbs.CertRecord;
import com.netscape.cmscore.dbs.CertificateRepository;
import com.netscape.cmscore.dbs.RevocationInfo;
import com.netscape.cmsutil.ldap.LDAPUtil;

/**
* @author Marco Fargetta <[email protected]>
*/
@WebServlet("/v2/certs/*")
public class CertServlet extends CAServlet {
public static final int DEFAULT_MAXTIME = 0;
public static final int DEFAULT_MAXRESULTS = 20;
public final static int DEFAULT_SIZE = 20;

private static final long serialVersionUID = 1L;
private static Logger logger = LoggerFactory.getLogger(CertServlet.class);

@Override
public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpSession session = request.getSession();
logger.debug("CertServlet.get(): session: {}", session.getId());

response.setContentType("application/json");
PrintWriter out = response.getWriter();
if(request.getPathInfo() != null) {
CertId id = new CertId(request.getPathInfo().substring(1));
CertData cert;
try {
cert = getCertData(id, request.getLocale());
out.println(cert.toJSON());
} catch (Exception e) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, request.getRequestURI());
}
return;
}

int maxResults = request.getParameter("maxResults") == null ?
DEFAULT_MAXRESULTS : Integer.parseInt(request.getParameter("maxResults"));
int maxTime = request.getParameter("maxTime") == null ?
DEFAULT_MAXTIME : Integer.parseInt(request.getParameter("maxTime"));
int size = request.getParameter("size") == null ?
DEFAULT_SIZE : Integer.parseInt(request.getParameter("size"));
int start = request.getParameter("start") == null ? 0 : Integer.parseInt(request.getParameter("start"));

CertDataInfos infos = listCerts(request.getParameter("status"), maxResults, maxTime, start, size);
out.println(infos.toJSON());
}

@Override
public void post(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpSession session = request.getSession();
logger.debug("CertServlet.post(): session: {}", session.getId());

response.setContentType("application/json");
PrintWriter out = response.getWriter();

if(request.getPathInfo() == null || !request.getPathInfo().equals("/search")) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, request.getRequestURI());
return;
}

CertDataInfos infos = new CertDataInfos();
out.println(infos.toString());
}

private CertData getCertData(CertId id, Locale loc) throws Exception {
CAEngine engine = getCAEngine();
CertificateRepository repo = engine.getCertificateRepository();

//find the cert in question
CertRecord record = repo.readCertificateRecord(id.toBigInteger());
X509CertImpl cert = record.getCertificate();

CertData certData = new CertData();
certData.setSerialNumber(id);

Principal issuerDN = cert.getIssuerName();
if (issuerDN != null) certData.setIssuerDN(issuerDN.toString());

Principal subjectDN = cert.getSubjectName();
if (subjectDN != null) certData.setSubjectDN(subjectDN.toString());

String base64 = CertUtil.toPEM(cert);
certData.setEncoded(base64);

CertPrettyPrint print = new CertPrettyPrint(cert);
certData.setPrettyPrint(print.toString(loc));

X509Certificate[] certChain = engine.getCertChain(cert);

PKCS7 pkcs7 = new PKCS7(
new AlgorithmId[0],
new ContentInfo(new byte[0]),
certChain,
new SignerInfo[0]);

ByteArrayOutputStream bos = new ByteArrayOutputStream();
pkcs7.encodeSignedData(bos, false);
byte[] p7Bytes = bos.toByteArray();

String p7Str = Utils.base64encode(p7Bytes, true);
certData.setPkcs7CertChain(p7Str);

Date notBefore = cert.getNotBefore();
if (notBefore != null) certData.setNotBefore(notBefore.toString());

Date notAfter = cert.getNotAfter();
if (notAfter != null) certData.setNotAfter(notAfter.toString());

certData.setRevokedOn(record.getRevokedOn());
certData.setRevokedBy(record.getRevokedBy());

RevocationInfo revInfo = record.getRevocationInfo();
if (revInfo != null) {
CRLExtensions revExts = revInfo.getCRLEntryExtensions();
if (revExts != null) {
try {
CRLReasonExtension ext = (CRLReasonExtension)
revExts.get(CRLReasonExtension.NAME);
certData.setRevocationReason(ext.getReason().getCode());
} catch (X509ExtensionException e) {
// nothing to do
}
}
}

certData.setStatus(record.getStatus());

return certData;
}

private CertDataInfos listCerts(String status, int maxResults, int maxTime, int start, int size) {
CAEngine engine = getCAEngine();
CertificateRepository repo = engine.getCertificateRepository();

logger.info("Listing certificates");

String filter;
if (status == null) {
filter = "(certstatus=*)";

} else {
filter = "(certStatus=" + LDAPUtil.escapeFilter(status) + ")";
}
logger.info("Search filter: " + filter);

CertDataInfos infos = new CertDataInfos();
try {
Enumeration<CertRecord> e = repo.searchCertificates(filter, maxResults, maxTime);
if (e == null) {
throw new EBaseException("search results are null");
}

// store non-null results in a list
List<CertDataInfo> results = new ArrayList<>();
while (e.hasMoreElements()) {
CertRecord rec = e.nextElement();
if (rec == null) continue;
results.add(createCertDataInfo(rec));
}

int total = results.size();
logger.info("Search results: " + total);
infos.setTotal(total);

// return entries in the requested page
for (int i = start; i < start + size && i < total ; i++) {
infos.addEntry(results.get(i));
}
} catch (Exception e) {
logger.error("Unable to list certificates: " + e.getMessage(), e);
throw new PKIException("Unable to list certificates: " + e.getMessage(), e);
}

return infos;
}

private CertDataInfo createCertDataInfo(CertRecord record) throws EBaseException, InvalidKeyException {
CertDataInfo info = new CertDataInfo();

CertId id = new CertId(record.getSerialNumber());
info.setID(id);

X509Certificate cert = record.getCertificate();
info.setIssuerDN(cert.getIssuerDN().toString());
info.setSubjectDN(cert.getSubjectDN().toString());
info.setStatus(record.getStatus());
info.setVersion(cert.getVersion());
info.setType(cert.getType());

PublicKey key = cert.getPublicKey();
if (key instanceof X509Key) {
X509Key x509Key = (X509Key)key;
info.setKeyAlgorithmOID(x509Key.getAlgorithmId().getOID().toString());

if (x509Key.getAlgorithmId().toString().equalsIgnoreCase("RSA")) {
RSAPublicKey rsaKey = new RSAPublicKey(x509Key.getEncoded());
info.setKeyLength(rsaKey.getKeySize());
}
}

info.setNotValidBefore(cert.getNotBefore());
info.setNotValidAfter(cert.getNotAfter());

info.setIssuedOn(record.getCreateTime());
info.setIssuedBy(record.getIssuedBy());

info.setRevokedOn(record.getRevokedOn());
info.setRevokedBy(record.getRevokedBy());

return info;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.netscape.certsrv.base.DataCollection;
import com.netscape.certsrv.util.JSONSerializer;

@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown=true)
public class CertDataInfos extends DataCollection<CertDataInfo> {
public class CertDataInfos extends DataCollection<CertDataInfo> implements JSONSerializer {

public Element toDOM(Document document) {

Expand Down

0 comments on commit 0493625

Please sign in to comment.