From ab3d3c8075a0b5244765a931ff11e6658130ade1 Mon Sep 17 00:00:00 2001 From: Endi Sukma Dewata Date: Tue, 8 Jan 2013 20:05:53 +0700 Subject: Added nonce validation for certificate revocation. The certificate REST service has been modified to validate nonce when revoking a certificate. Ticket #213 --- .../src/com/netscape/certsrv/cert/CertClient.java | 4 ++ .../src/com/netscape/certsrv/cert/CertData.java | 17 +++++ .../com/netscape/certsrv/cert/CertResource.java | 6 ++ .../netscape/certsrv/cert/CertRevokeRequest.java | 18 ++++++ .../com/netscape/cms/servlet/cert/CertService.java | 44 +++++++++++-- .../com/netscape/cms/servlet/cert/DoRevoke.java | 72 ++++++---------------- .../cms/servlet/cert/RevocationProcessor.java | 54 +++++++++++++++- .../netscape/cms/servlet/processors/Processor.java | 2 + .../com/netscape/cmstools/cert/CertHoldCLI.java | 7 ++- .../com/netscape/cmstools/cert/CertRevokeCLI.java | 8 ++- 10 files changed, 166 insertions(+), 66 deletions(-) diff --git a/base/common/src/com/netscape/certsrv/cert/CertClient.java b/base/common/src/com/netscape/certsrv/cert/CertClient.java index da60ed085..d8fd34658 100644 --- a/base/common/src/com/netscape/certsrv/cert/CertClient.java +++ b/base/common/src/com/netscape/certsrv/cert/CertClient.java @@ -52,6 +52,10 @@ public class CertClient extends PKIClient { return certClient.getCert(id); } + public CertData reviewCert(CertId id) { + return certClient.reviewCert(id); + } + public CertDataInfos findCerts(CertSearchRequest data, Integer start, Integer size) { return certClient.searchCerts(data, start, size); } diff --git a/base/common/src/com/netscape/certsrv/cert/CertData.java b/base/common/src/com/netscape/certsrv/cert/CertData.java index 58f7fcd2c..1c75d8f7c 100644 --- a/base/common/src/com/netscape/certsrv/cert/CertData.java +++ b/base/common/src/com/netscape/certsrv/cert/CertData.java @@ -63,6 +63,7 @@ public class CertData { String notBefore; String notAfter; String status; + Long nonce; Link link; @@ -148,6 +149,15 @@ public class CertData { this.status = status; } + @XmlElement(name="Nonce") + public Long getNonce() { + return nonce; + } + + public void setNonce(Long nonce) { + this.nonce = nonce; + } + @XmlElement(name="Link") public Link getLink() { return link; @@ -163,6 +173,7 @@ public class CertData { int result = 1; result = prime * result + ((encoded == null) ? 0 : encoded.hashCode()); result = prime * result + ((issuerDN == null) ? 0 : issuerDN.hashCode()); + result = prime * result + ((nonce == null) ? 0 : nonce.hashCode()); result = prime * result + ((notAfter == null) ? 0 : notAfter.hashCode()); result = prime * result + ((notBefore == null) ? 0 : notBefore.hashCode()); result = prime * result + ((pkcs7CertChain == null) ? 0 : pkcs7CertChain.hashCode()); @@ -192,6 +203,11 @@ public class CertData { return false; } else if (!issuerDN.equals(other.issuerDN)) return false; + if (nonce == null) { + if (other.nonce != null) + return false; + } else if (!nonce.equals(other.nonce)) + return false; if (notAfter == null) { if (other.notAfter != null) return false; @@ -273,6 +289,7 @@ public class CertData { before.setIssuerDN("CN=Test User,UID=testuser,O=EXAMPLE-COM"); before.setSubjectDN("CN=Test User,UID=testuser,O=EXAMPLE-COM"); before.setEncoded(sw.toString()); + before.setNonce(12345l); String string = before.toString(); System.out.println(string); diff --git a/base/common/src/com/netscape/certsrv/cert/CertResource.java b/base/common/src/com/netscape/certsrv/cert/CertResource.java index 53e06ca6e..17395032d 100644 --- a/base/common/src/com/netscape/certsrv/cert/CertResource.java +++ b/base/common/src/com/netscape/certsrv/cert/CertResource.java @@ -41,6 +41,12 @@ public interface CertResource { @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public CertData getCert(@PathParam("id") CertId id); + @GET + @Path("agent/certs/{id}") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + @ACLMapping("agent.certs") + public CertData reviewCert(@PathParam("id") CertId id); + @POST @Path("agent/certs/{id}/revoke-ca") @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) diff --git a/base/common/src/com/netscape/certsrv/cert/CertRevokeRequest.java b/base/common/src/com/netscape/certsrv/cert/CertRevokeRequest.java index 7b86286ce..0fe0c4696 100644 --- a/base/common/src/com/netscape/certsrv/cert/CertRevokeRequest.java +++ b/base/common/src/com/netscape/certsrv/cert/CertRevokeRequest.java @@ -63,6 +63,7 @@ public class CertRevokeRequest { Date invalidityDate; String comments; String encoded; + Long nonce; @XmlElement(name="RequestID") @@ -118,6 +119,16 @@ public class CertRevokeRequest { this.encoded = encoded; } + @XmlElement(name="Nonce") + @FormParam("nonce") + public Long getNonce() { + return nonce; + } + + public void setNonce(Long nonce) { + this.nonce = nonce; + } + @Override public int hashCode() { final int prime = 31; @@ -125,6 +136,7 @@ public class CertRevokeRequest { result = prime * result + ((comments == null) ? 0 : comments.hashCode()); result = prime * result + ((encoded == null) ? 0 : encoded.hashCode()); result = prime * result + ((invalidityDate == null) ? 0 : invalidityDate.hashCode()); + result = prime * result + ((nonce == null) ? 0 : nonce.hashCode()); result = prime * result + ((reason == null) ? 0 : reason.hashCode()); result = prime * result + ((requestID == null) ? 0 : requestID.hashCode()); return result; @@ -154,6 +166,11 @@ public class CertRevokeRequest { return false; } else if (!invalidityDate.equals(other.invalidityDate)) return false; + if (nonce == null) { + if (other.nonce != null) + return false; + } else if (!nonce.equals(other.nonce)) + return false; if (reason == null) { if (other.reason != null) return false; @@ -194,6 +211,7 @@ public class CertRevokeRequest { before.setInvalidityDate(new Date()); before.setComments("test"); before.setEncoded("test"); + before.setNonce(12345l); String string = before.toString(); System.out.println(string); diff --git a/base/common/src/com/netscape/cms/servlet/cert/CertService.java b/base/common/src/com/netscape/cms/servlet/cert/CertService.java index 9b7b9d45e..e049710cb 100644 --- a/base/common/src/com/netscape/cms/servlet/cert/CertService.java +++ b/base/common/src/com/netscape/cms/servlet/cert/CertService.java @@ -29,6 +29,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; import java.util.List; +import java.util.Random; import netscape.security.pkcs.ContentInfo; import netscape.security.pkcs.PKCS7; @@ -43,6 +44,7 @@ import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.base.BadRequestException; import com.netscape.certsrv.base.EBaseException; import com.netscape.certsrv.base.ICertPrettyPrint; +import com.netscape.certsrv.base.Nonces; import com.netscape.certsrv.base.PKIException; import com.netscape.certsrv.base.UnauthorizedException; import com.netscape.certsrv.ca.ICertificateAuthority; @@ -65,6 +67,7 @@ import com.netscape.certsrv.logging.ILogger; import com.netscape.certsrv.request.IRequest; import com.netscape.cms.servlet.base.PKIService; import com.netscape.cms.servlet.processors.Processor; +import com.netscape.cmscore.realm.PKIPrincipal; import com.netscape.cmsutil.ldap.LDAPUtil; import com.netscape.cmsutil.util.Utils; @@ -76,11 +79,17 @@ public class CertService extends PKIService implements CertResource { ICertificateAuthority authority; ICertificateRepository repo; + Random random; + Nonces nonces; public final static int DEFAULT_SIZE = 20; public CertService() { authority = (ICertificateAuthority) CMS.getSubsystem("ca"); + if (authority.noncesEnabled()) { + random = new Random(); + nonces = authority.getNonces(); + } repo = authority.getCertificateRepository(); } @@ -92,6 +101,15 @@ public class CertService extends PKIService implements CertResource { @Override public CertData getCert(CertId id) { + return getCert(id, false); + } + + @Override + public CertData reviewCert(CertId id) { + return getCert(id, true); + } + + public CertData getCert(CertId id, boolean generateNonce) { validateRequest(id); CertRetrievalRequest data = new CertRetrievalRequest(); @@ -100,13 +118,13 @@ public class CertService extends PKIService implements CertResource { CertData certData = null; try { - certData = getCert(data); + certData = getCert(data, generateNonce); } catch (EDBRecordNotFoundException e) { throw new CertNotFoundException(id); } catch (EBaseException e) { - throw new PKIException("Problem returning certificate: " + id); + throw new PKIException(e.getMessage(), e); } catch (CertificateEncodingException e) { - throw new PKIException("Problem encoding certificate searched for: " + id); + throw new PKIException(e.getMessage(), e); } return certData; @@ -177,12 +195,20 @@ public class CertService extends PKIService implements CertResource { } } + processor.validateNonce(clientCert, request.getNonce()); + // Find target cert record if different from client cert. ICertRecord targetRecord = id.equals(clientSerialNumber) ? clientRecord : processor.getCertificateRecord(id); X509CertImpl targetCert = targetRecord.getCertificate(); processor.createCRLExtension(); - processor.validateCertificateToRevoke(clientSubjectDN, targetRecord, caCert); + + PKIPrincipal principal = (PKIPrincipal)servletRequest.getUserPrincipal(); + // TODO: do not hard-code role name + String subjectDN = principal.hasRole("Certificate Manager Agents") ? + null : clientSubjectDN; + + processor.validateCertificateToRevoke(subjectDN, targetRecord, caCert); processor.addCertificateToRevoke(targetCert); processor.createRevocationRequest(); @@ -410,7 +436,7 @@ public class CertService extends PKIService implements CertResource { return ret; } - public CertData getCert(CertRetrievalRequest data) throws EBaseException, CertificateEncodingException { + public CertData getCert(CertRetrievalRequest data, boolean generateNonce) throws EBaseException, CertificateEncodingException { CertId certId = data.getCertId(); //find the cert in question @@ -444,6 +470,14 @@ public class CertService extends PKIService implements CertResource { certData.setStatus(record.getStatus()); + if (generateNonce && nonces != null) { + long n = random.nextLong(); + long m = nonces.addNonce(n, Processor.getSSLClientCertificate(servletRequest)); + if (n + m != 0) { + certData.setNonce(m); + } + } + URI uri = uriInfo.getBaseUriBuilder().path(CertResource.class).path("{id}").build(certId.toHexString()); certData.setLink(new Link("self", uri)); diff --git a/base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java b/base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java index f45947e8c..5d33bf2bc 100644 --- a/base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java +++ b/base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java @@ -47,6 +47,7 @@ import com.netscape.certsrv.authority.ICertAuthority; import com.netscape.certsrv.authorization.AuthzToken; import com.netscape.certsrv.authorization.EAuthzAccessDenied; import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.ForbiddenException; import com.netscape.certsrv.base.IArgBlock; import com.netscape.certsrv.base.Nonces; import com.netscape.certsrv.base.PKIException; @@ -62,10 +63,8 @@ import com.netscape.certsrv.ra.IRegistrationAuthority; import com.netscape.certsrv.request.IRequest; import com.netscape.certsrv.request.RequestId; import com.netscape.certsrv.request.RequestStatus; -import com.netscape.certsrv.usrgrp.Certificates; import com.netscape.certsrv.usrgrp.ICertUserLocator; import com.netscape.certsrv.usrgrp.IUGSubsystem; -import com.netscape.certsrv.usrgrp.IUser; import com.netscape.cms.servlet.base.CMSServlet; import com.netscape.cms.servlet.common.CMSRequest; import com.netscape.cms.servlet.common.CMSTemplate; @@ -207,47 +206,6 @@ public class DoRevoke extends CMSServlet { } revokeAll = req.getParameter("revokeAll"); - if (mNonces != null) { - boolean nonceVerified = false; - boolean skipNonceVerification = false; - - X509Certificate cert2 = getSSLClientCertificate(req); - if (cert2 != null) { - X509Certificate certChain[] = new X509Certificate[1]; - certChain[0] = cert2; - IUser user = null; - try { - user = mUL.locateUser(new Certificates(certChain)); - } catch (Exception e) { - CMS.debug("DoRevoke: Failed to map certificate '" + - cert2.getSubjectDN().getName() + "' to user."); - } - if (mUG.isMemberOf(user, "Subsystem Group")) { - skipNonceVerification = true; - } - } - - String nonceStr = req.getParameter("nonce"); - if (nonceStr != null) { - long nonce = Long.parseLong(nonceStr.trim()); - X509Certificate cert1 = mNonces.getCertificate(nonce); - if (cert1 == null) { - CMS.debug("DoRevoke: Unknown nonce"); - } else if (cert1 != null && cert2 != null && cert1.equals(cert2)) { - nonceVerified = true; - mNonces.removeNonce(nonce); - } - } else { - CMS.debug("DoRevoke: Missing nonce"); - } - CMS.debug("DoRevoke: nonceVerified=" + nonceVerified); - CMS.debug("DoRevoke: skipNonceVerification=" + skipNonceVerification); - if ((!nonceVerified) && (!skipNonceVerification)) { - cmsReq.setStatus(CMSRequest.UNAUTHORIZED); - return; - } - } - String comments = req.getParameter(IRequest.REQUESTOR_COMMENTS); String eeSubjectDN = null; String eeSerialNumber = null; @@ -279,11 +237,13 @@ public class DoRevoke extends CMSServlet { if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) { if (authToken != null) { + // Request is from agent. String serialNumber = req.getParameter("serialNumber"); getSSLClientCertificate(req); // throw exception on error if (serialNumber != null) { + // Agent has null subject DN. eeSerialNumber = serialNumber; } @@ -294,7 +254,7 @@ public class DoRevoke extends CMSServlet { " authenticated by " + authMgr; } } else { - // request is fromUser. + // Request is from user. initiative = AuditFormat.FROMUSER; String serialNumber = req.getParameter("serialNumber"); @@ -302,7 +262,8 @@ public class DoRevoke extends CMSServlet { if (serialNumber == null || sslCert == null || !(serialNumber.equals(sslCert.getSerialNumber().toString(16)))) { - authorized = false; + throw new ForbiddenException("Invalid serial number."); + } else { eeSubjectDN = sslCert.getSubjectDN().toString(); eeSerialNumber = sslCert.getSerialNumber().toString(); @@ -310,19 +271,21 @@ public class DoRevoke extends CMSServlet { } - if (authorized) { - BigInteger serialNumber = parseSerialNumber(eeSerialNumber); + BigInteger serialNumber = parseSerialNumber(eeSerialNumber); - process(argSet, header, reason, invalidityDate, initiative, - req, resp, verifiedRecordCount, revokeAll, - totalRecordCount, serialNumber, eeSubjectDN, - comments, locale[0]); - } + process(argSet, header, reason, invalidityDate, initiative, + req, resp, verifiedRecordCount, revokeAll, + totalRecordCount, serialNumber, eeSubjectDN, + comments, locale[0]); } catch (NumberFormatException e) { log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT")); error = new EBaseException(CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT")); + + } catch (ForbiddenException e) { + authorized = false; + } catch (EBaseException e) { error = e; } @@ -442,6 +405,11 @@ public class DoRevoke extends CMSServlet { processor.setAuthority((ICertificateAuthority)mAuthority); } + X509Certificate clientCert = getSSLClientCertificate(req); + String requestedNonce = req.getParameter("nonce"); + Long nonce = requestedNonce == null ? null : new Long(requestedNonce.trim()); + processor.validateNonce(clientCert, nonce); + try { processor.createCRLExtension(); diff --git a/base/common/src/com/netscape/cms/servlet/cert/RevocationProcessor.java b/base/common/src/com/netscape/cms/servlet/cert/RevocationProcessor.java index 36d00459b..341314887 100644 --- a/base/common/src/com/netscape/cms/servlet/cert/RevocationProcessor.java +++ b/base/common/src/com/netscape/cms/servlet/cert/RevocationProcessor.java @@ -38,6 +38,7 @@ import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.base.BadRequestException; import com.netscape.certsrv.base.EBaseException; import com.netscape.certsrv.base.EPropertyNotFound; +import com.netscape.certsrv.base.ForbiddenException; import com.netscape.certsrv.base.UnauthorizedException; import com.netscape.certsrv.ca.ICertificateAuthority; import com.netscape.certsrv.dbs.certdb.CertId; @@ -50,6 +51,8 @@ import com.netscape.certsrv.request.IRequest; import com.netscape.certsrv.request.IRequestQueue; import com.netscape.certsrv.request.RequestId; import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.usrgrp.Certificates; +import com.netscape.certsrv.usrgrp.IUser; /** * @author Endi S. Dewata @@ -185,14 +188,59 @@ public class RevocationProcessor extends CertProcessor { return request; } - public void validateCertificateToRevoke(String clientSubjectDN, ICertRecord targetRecord, boolean revokingCACert) { + public void validateNonce(X509Certificate clientCert, Long nonce) { + + if (nonces != null) { + boolean nonceVerified = false; + boolean skipNonceVerification = false; + + if (clientCert != null) { + X509Certificate certChain[] = new X509Certificate[1]; + certChain[0] = clientCert; + IUser user = null; + try { + user = ul.locateUser(new Certificates(certChain)); + } catch (Exception e) { + CMS.debug("RevocationProcessor: Failed to map certificate '" + + clientCert.getSubjectDN().getName() + "' to user."); + } + if (ug.isMemberOf(user, "Subsystem Group")) { + skipNonceVerification = true; + } + } + + if (nonce != null) { + X509Certificate storedCert = nonces.getCertificate(nonce); + if (storedCert == null) { + CMS.debug("RevocationProcessor: Unknown nonce"); + + } else if (clientCert != null && storedCert.equals(clientCert)) { + nonceVerified = true; + nonces.removeNonce(nonce); + } + } else { + CMS.debug("RevocationProcessor: Missing nonce"); + } + + CMS.debug("RevocationProcessor: nonceVerified=" + nonceVerified); + CMS.debug("RevocationProcessor: skipNonceVerification=" + skipNonceVerification); + if ((!nonceVerified) && (!skipNonceVerification)) { + throw new ForbiddenException("Invalid nonce."); + } + } + + } + + public void validateCertificateToRevoke(String subjectDN, ICertRecord targetRecord, boolean revokingCACert) { X509CertImpl targetCert = targetRecord.getCertificate(); BigInteger targetSerialNumber = targetCert.getSerialNumber(); Principal targetSubjectDN = targetCert.getSubjectDN(); - // Verify client cert's subject DN matches the target cert's subject DN. - if (clientSubjectDN != null && !clientSubjectDN.equals(targetSubjectDN.toString())) { + // Verify the subject DN matches the target cert's subject DN. + // Agent has null subject DN so he can revoke any certificate. + // Other users can only revoke their own certificate. + if (subjectDN != null && !subjectDN.equals(targetSubjectDN.toString())) { throw new UnauthorizedException( "Certificate 0x" + targetSerialNumber.toString(16) + " belongs to different subject."); } diff --git a/base/common/src/com/netscape/cms/servlet/processors/Processor.java b/base/common/src/com/netscape/cms/servlet/processors/Processor.java index fdbc85dd5..423d1bed5 100644 --- a/base/common/src/com/netscape/cms/servlet/processors/Processor.java +++ b/base/common/src/com/netscape/cms/servlet/processors/Processor.java @@ -59,6 +59,7 @@ import com.netscape.certsrv.profile.IProfileSubsystem; import com.netscape.certsrv.request.IRequest; import com.netscape.certsrv.request.IRequestQueue; import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.usrgrp.ICertUserLocator; import com.netscape.certsrv.usrgrp.IGroup; import com.netscape.certsrv.usrgrp.IUGSubsystem; import com.netscape.certsrv.util.IStatsSubsystem; @@ -144,6 +145,7 @@ public class Processor { protected ICertificateAuthority authority = (ICertificateAuthority) CMS.getSubsystem("ca"); protected IAuthzSubsystem authz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ); protected IUGSubsystem ug = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG); + protected ICertUserLocator ul = ug.getCertUserLocator(); protected IRequestQueue queue; protected IProfileSubsystem ps; protected ICertificateRepository certdb; diff --git a/base/java-tools/src/com/netscape/cmstools/cert/CertHoldCLI.java b/base/java-tools/src/com/netscape/cmstools/cert/CertHoldCLI.java index b5c604a86..a112d3616 100644 --- a/base/java-tools/src/com/netscape/cmstools/cert/CertHoldCLI.java +++ b/base/java-tools/src/com/netscape/cmstools/cert/CertHoldCLI.java @@ -77,14 +77,14 @@ public class CertHoldCLI extends CLI { } CertId certID = new CertId(cmdArgs[0]); + CertData certData = parent.client.reviewCert(certID); if (!cmd.hasOption("force")) { - CertData certData = parent.client.getCert(certID); - System.out.println("Placing certificate on-hold:"); CertCLI.printCertData(certData, false, false); + if (verbose) System.out.println(" Nonce: " + certData.getNonce()); System.out.print("Are you sure (Y/N)? "); System.out.flush(); @@ -99,6 +99,7 @@ public class CertHoldCLI extends CLI { CertRevokeRequest request = new CertRevokeRequest(); request.setReason(RevocationReason.CERTIFICATE_HOLD); request.setComments(cmd.getOptionValue("comments")); + request.setNonce(certData.getNonce()); CertRequestInfo certRequestInfo = parent.client.revokeCert(certID, request); @@ -108,7 +109,7 @@ public class CertHoldCLI extends CLI { if (certRequestInfo.getRequestStatus() == RequestStatus.COMPLETE) { MainCLI.printMessage("Placed certificate \"" + certID.toHexString() + "\" on-hold"); - CertData certData = parent.client.getCert(certID); + certData = parent.client.getCert(certID); CertCLI.printCertData(certData, false, false); } else { diff --git a/base/java-tools/src/com/netscape/cmstools/cert/CertRevokeCLI.java b/base/java-tools/src/com/netscape/cmstools/cert/CertRevokeCLI.java index d8a4d5295..1a867d079 100644 --- a/base/java-tools/src/com/netscape/cmstools/cert/CertRevokeCLI.java +++ b/base/java-tools/src/com/netscape/cmstools/cert/CertRevokeCLI.java @@ -105,9 +105,9 @@ public class CertRevokeCLI extends CLI { return; } - if (!cmd.hasOption("force")) { + CertData certData = parent.client.reviewCert(certID); - CertData certData = parent.client.getCert(certID); + if (!cmd.hasOption("force")) { if (reason == RevocationReason.CERTIFICATE_HOLD) { System.out.println("Placing certificate on-hold:"); @@ -118,6 +118,7 @@ public class CertRevokeCLI extends CLI { } CertCLI.printCertData(certData, false, false); + if (verbose) System.out.println(" Nonce: " + certData.getNonce()); System.out.print("Are you sure (Y/N)? "); System.out.flush(); @@ -132,6 +133,7 @@ public class CertRevokeCLI extends CLI { CertRevokeRequest request = new CertRevokeRequest(); request.setReason(reason); request.setComments(cmd.getOptionValue("comments")); + request.setNonce(certData.getNonce()); CertRequestInfo certRequestInfo; @@ -154,7 +156,7 @@ public class CertRevokeCLI extends CLI { MainCLI.printMessage("Revoked certificate \"" + certID.toHexString() + "\""); } - CertData certData = parent.client.getCert(certID); + certData = parent.client.getCert(certID); CertCLI.printCertData(certData, false, false); } else { -- cgit