// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package com.netscape.cms.servlet.common; import org.mozilla.jss.asn1.*; import org.mozilla.jss.pkix.cmc.*; import org.mozilla.jss.pkix.cmmf.*; import org.mozilla.jss.pkix.primitive.*; import java.io.*; import java.util.*; import java.math.*; import javax.servlet.http.*; import com.netscape.certsrv.dbs.certdb.*; import com.netscape.certsrv.apps.*; import com.netscape.certsrv.authentication.*; import com.netscape.certsrv.base.*; import com.netscape.certsrv.logging.*; import com.netscape.certsrv.request.*; import com.netscape.certsrv.dbs.certdb.ICertificateRepository; import com.netscape.certsrv.base.SessionContext; import org.mozilla.jss.pkix.cms.*; import org.mozilla.jss.pkix.cert.*; import org.mozilla.jss.crypto.*; import org.mozilla.jss.*; import netscape.security.x509.*; import com.netscape.certsrv.profile.*; import com.netscape.certsrv.ca.*; import com.netscape.certsrv.security.*; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import org.mozilla.jss.pkcs11.PK11PubKey; /** * Utility CMCOutputTemplate * * @version $ $, $Date$ */ public class CMCOutputTemplate { public CMCOutputTemplate() { } public void createFullResponseWithFailedStatus(HttpServletResponse resp, SEQUENCE bpids, int code, UTF8String s) { SEQUENCE controlSeq = new SEQUENCE(); SEQUENCE cmsSeq = new SEQUENCE(); SEQUENCE otherMsgSeq = new SEQUENCE(); int bpid = 1; OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(code), null); CMCStatusInfo cmcStatusInfo = new CMCStatusInfo( new INTEGER(CMCStatusInfo.FAILED), bpids, s, otherInfo); TaggedAttribute tagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); controlSeq.addElement(tagattr); try { ResponseBody respBody = new ResponseBody(controlSeq, cmsSeq, otherMsgSeq); SET certs = new SET(); ContentInfo contentInfo = getContentInfo(respBody, certs); if (contentInfo == null) return; ByteArrayOutputStream fos = new ByteArrayOutputStream(); contentInfo.encode(fos); fos.close(); byte[] contentBytes = fos.toByteArray(); resp.setContentType("application/pkcs7-mime"); resp.setContentLength(contentBytes.length); OutputStream os = resp.getOutputStream(); os.write(contentBytes); os.flush(); } catch (Exception e) { CMS.debug("CMCOutputTemplate createFullResponseWithFailedStatus Exception: "+e.toString()); return; } } public void createFullResponse(HttpServletResponse resp, IRequest []reqs, String cert_request_type, int[] error_codes) { SEQUENCE controlSeq = new SEQUENCE(); SEQUENCE cmsSeq = new SEQUENCE(); SEQUENCE otherMsgSeq = new SEQUENCE(); SessionContext context = SessionContext.getContext(); // set status info control for simple enrollment request // in rfc 2797: body list value is 1 int bpid = 1; SEQUENCE pending_bpids = null; SEQUENCE success_bpids = null; SEQUENCE failed_bpids = null; if (cert_request_type.equals("crmf") || cert_request_type.equals("pkcs10")) { String reqId = reqs[0].getRequestId().toString(); OtherInfo otherInfo = null; if (error_codes[0] == 2) { PendInfo pendInfo = new PendInfo(reqId, new Date()); otherInfo = new OtherInfo(OtherInfo.PEND, null, pendInfo); } else { otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_REQUEST), null); } SEQUENCE bpids = new SEQUENCE(); bpids.addElement(new INTEGER(1)); CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.PENDING, bpids, (String)null, otherInfo); TaggedAttribute tagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); controlSeq.addElement(tagattr); } else if (cert_request_type.equals("cmc")) { pending_bpids = new SEQUENCE(); success_bpids = new SEQUENCE(); failed_bpids = new SEQUENCE(); if (reqs != null) { for (int i=0; i 0) { OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_IDENTITY), null); cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, identityBpids, (String)null, otherInfo); tagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); controlSeq.addElement(tagattr); } SEQUENCE POPLinkWitnessBpids = (SEQUENCE)context.get("POPLinkWitness"); if (POPLinkWitnessBpids != null && POPLinkWitnessBpids.size() > 0) { OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_REQUEST), null); cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, POPLinkWitnessBpids, (String)null, otherInfo); tagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); controlSeq.addElement(tagattr); } if (pending_bpids.size() > 0) { cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.PENDING, pending_bpids, (String)null, null); tagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); controlSeq.addElement(tagattr); } if (success_bpids.size() > 0) { boolean confirmRequired = false; try { confirmRequired = CMS.getConfigStore().getBoolean("cmc.cert.confirmRequired", false); } catch (Exception e) { } if (confirmRequired) { CMS.debug("CMCOutputTemplate: confirmRequired in the request"); cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.CONFIRM_REQUIRED, success_bpids, (String)null, null); } else { cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS, success_bpids, (String)null, null); } tagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); controlSeq.addElement(tagattr); } if (failed_bpids.size() > 0) { OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_REQUEST), null); cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String)null, otherInfo); tagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); controlSeq.addElement(tagattr); } } SET certs = new SET(); try { // deal with controls Integer nums = (Integer)(context.get("numOfControls")); if (nums != null && nums.intValue() > 0) { TaggedAttribute attr = (TaggedAttribute)(context.get(OBJECT_IDENTIFIER.id_cmc_getCert)); if (attr != null) { try { processGetCertControl(attr, certs); } catch (EBaseException ee) { CMS.debug("CMCOutputTemplate: "+ee.toString()); OtherInfo otherInfo1 = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_CERT_ID), null); SEQUENCE bpids1 = new SEQUENCE(); bpids1.addElement(attr.getBodyPartID()); CMCStatusInfo cmcStatusInfo1 = new CMCStatusInfo( new INTEGER(CMCStatusInfo.FAILED), bpids1, null, otherInfo1); TaggedAttribute tagattr1 = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo1); controlSeq.addElement(tagattr1); } } attr = (TaggedAttribute)(context.get(OBJECT_IDENTIFIER.id_cmc_dataReturn)); if (attr != null) bpid = processDataReturnControl(attr, controlSeq, bpid); attr = (TaggedAttribute)context.get(OBJECT_IDENTIFIER.id_cmc_transactionId); if (attr != null) bpid = processTransactionControl(attr, controlSeq, bpid); attr = (TaggedAttribute)context.get(OBJECT_IDENTIFIER.id_cmc_senderNonce); if (attr != null) bpid = processSenderNonceControl(attr, controlSeq, bpid); attr = (TaggedAttribute)context.get(OBJECT_IDENTIFIER.id_cmc_QueryPending); if (attr != null) bpid = processQueryPendingControl(attr, controlSeq, bpid); attr = (TaggedAttribute)context.get(OBJECT_IDENTIFIER.id_cmc_idConfirmCertAcceptance); if (attr != null) bpid = processConfirmCertAcceptanceControl(attr, controlSeq, bpid); attr = (TaggedAttribute)context.get(OBJECT_IDENTIFIER.id_cmc_revokeRequest); if (attr != null) bpid = processRevokeRequestControl(attr, controlSeq, bpid); } if (success_bpids != null && success_bpids.size() > 0) { for (int i=0; i 0) { try { CMCCertId cmcCertId = (CMCCertId)(ASN1Util.decode(CMCCertId.getTemplate(), ASN1Util.encode(values.elementAt(0)))); BigInteger serialno = (BigInteger)(cmcCertId.getSerial()); SEQUENCE issuers = cmcCertId.getIssuer(); //ANY issuer = (ANY)issuers.elementAt(0); ANY issuer = (ANY)(ASN1Util.decode(ANY.getTemplate(), ASN1Util.encode(issuers.elementAt(0)))); byte[] b = issuer.getEncoded(); X500Name n = new X500Name(b); ICertificateAuthority ca = null; ca = (ICertificateAuthority)CMS.getSubsystem("ca"); X500Name caName = ca.getX500Name(); boolean confirmAccepted = false; if (n.toString().equalsIgnoreCase(caName.toString())) { CMS.debug("CMCOutputTemplate: Issuer names are equal"); ICertificateRepository repository = (ICertificateRepository)ca.getCertificateRepository(); X509CertImpl impl = null; try { repository.getX509Certificate(serialno); } catch (EBaseException ee) { CMS.debug("CMCOutputTemplate: Certificate in the confirm acceptance control was not found"); } if (impl != null) confirmAccepted = true; } CMCStatusInfo cmcStatusInfo = null; if (confirmAccepted) { CMS.debug("CMCOutputTemplate: Confirm Acceptance received. The certificate exists in the certificate repository."); cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS, seq, (String)null, null); } else { CMS.debug("CMCOutputTemplate: Confirm Acceptance received. The certificate does not exist in the certificate repository."); OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_CERT_ID), null); cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, seq, (String)null, otherInfo); } TaggedAttribute statustagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); controlSeq.addElement(statustagattr); } catch (Exception e) { CMS.debug("CMCOutputTemplate exception: "+e.toString()); } } } return bpid; } private void processGetCertControl(TaggedAttribute attr, SET certs) throws InvalidBERException, java.security.cert.CertificateEncodingException, IOException, EBaseException { if (attr != null) { SET vals = attr.getValues(); if (vals.size() == 1) { GetCert getCert = (GetCert)(ASN1Util.decode(GetCert.getTemplate(), ASN1Util.encode(vals.elementAt(0)))); BigInteger serialno = (BigInteger)(getCert.getSerialNumber()); ANY issuer = (ANY)getCert.getIssuer(); byte b[] = issuer.getEncoded(); X500Name n = new X500Name(b); ICertificateAuthority ca = (ICertificateAuthority)CMS.getSubsystem("ca"); X500Name caName = ca.getX500Name(); if (!n.toString().equalsIgnoreCase(caName.toString())) { CMS.debug("CMCOutputTemplate: Issuer names are equal in the GetCert Control"); throw new EBaseException("Certificate is not found"); } ICertificateRepository repository = (ICertificateRepository)ca.getCertificateRepository(); X509CertImpl impl = repository.getX509Certificate(serialno); byte[] bin = impl.getEncoded(); Certificate.Template certTemplate = new Certificate.Template(); Certificate cert = (Certificate)certTemplate.decode(new ByteArrayInputStream(bin)); certs.addElement(cert); } } } private int processQueryPendingControl(TaggedAttribute attr, SEQUENCE controlSeq, int bpid) { if (attr != null) { SET values = attr.getValues(); if (values != null && values.size() > 0) { SEQUENCE pending_bpids = new SEQUENCE(); SEQUENCE success_bpids = new SEQUENCE(); SEQUENCE failed_bpids = new SEQUENCE(); for (int i=0; i 0) { CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.PENDING, pending_bpids, (String)null, null); TaggedAttribute tagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); controlSeq.addElement(tagattr); } if (success_bpids.size() > 0) { CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS, pending_bpids, (String)null, null); TaggedAttribute tagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); controlSeq.addElement(tagattr); } if (failed_bpids.size() > 0) { CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, pending_bpids, (String)null, null); TaggedAttribute tagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); controlSeq.addElement(tagattr); } } } return bpid; } private int processTransactionControl(TaggedAttribute attr, SEQUENCE controlSeq, int bpid) { if (attr != null) { SET transIds = attr.getValues(); if (transIds != null) { TaggedAttribute tagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_transactionId, transIds); controlSeq.addElement(tagattr); } } return bpid; } private int processSenderNonceControl(TaggedAttribute attr, SEQUENCE controlSeq, int bpid) { if (attr != null) { SET sNonce = attr.getValues(); if (sNonce != null) { TaggedAttribute tagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_recipientNonce, sNonce); controlSeq.addElement(tagattr); Date date = new Date(); String salt = "lala123"+date.toString(); byte[] dig; try { MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1"); dig = SHA1Digest.digest(salt.getBytes()); } catch (NoSuchAlgorithmException ex) { dig = salt.getBytes(); } String b64E = CMS.BtoA(dig); tagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_senderNonce, new OCTET_STRING(b64E.getBytes())); controlSeq.addElement(tagattr); } } return bpid; } private int processDataReturnControl(TaggedAttribute attr, SEQUENCE controlSeq, int bpid) throws InvalidBERException { if (attr != null) { SET vals = attr.getValues(); if (vals.size() > 0) { OCTET_STRING str = (OCTET_STRING)(ASN1Util.decode(OCTET_STRING.getTemplate(), ASN1Util.encode(vals.elementAt(0)))); TaggedAttribute tagattr = new TaggedAttribute( new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_dataReturn, str); controlSeq.addElement(tagattr); } } return bpid; } private int processRevokeRequestControl(TaggedAttribute attr, SEQUENCE controlSeq, int bpid) throws InvalidBERException, EBaseException, IOException { boolean revoke = false; SessionContext context = SessionContext.getContext(); if (attr != null) { INTEGER attrbpid = attr.getBodyPartID(); CMCStatusInfo cmcStatusInfo = null; SET vals = attr.getValues(); if (vals.size() > 0) { RevRequest revRequest = (RevRequest)(ASN1Util.decode(new RevRequest.Template(), ASN1Util.encode(vals.elementAt(0)))); OCTET_STRING str = revRequest.getSharedSecret(); INTEGER pid = attr.getBodyPartID(); TaggedAttribute tagattr = null; INTEGER revokeCertSerial = revRequest.getSerialNumber(); BigInteger revokeSerial = new BigInteger(revokeCertSerial.toByteArray()); if (str == null) { boolean needVerify = true; try { needVerify = CMS.getConfigStore().getBoolean("cmc.revokeCert.verify", true); } catch (Exception e) { } if (needVerify) { Integer num1 = (Integer)context.get("numOfOtherMsgs"); int num = num1.intValue(); for (int i=0; i 0) revRequest = (RevRequest)(ASN1Util.decode(new RevRequest.Template(), ASN1Util.encode(values.elementAt(0)))); SET dias = msgData.getDigestAlgorithmIdentifiers(); int numDig = dias.size(); Hashtable digs = new Hashtable(); for (int i=0; i