diff options
author | Endi S. Dewata <edewata@redhat.com> | 2013-10-07 11:48:54 -0400 |
---|---|---|
committer | Endi S. Dewata <edewata@redhat.com> | 2013-10-25 17:17:39 -0400 |
commit | 2119f1b218e9d68b13496e7042785d9c68753966 (patch) | |
tree | b8c7cf5692723340d8d56e5d8c401acdee059ca5 /base/server/cms/src/com/netscape/cms/servlet/processors | |
parent | 7ca5adf1bd5bc4f9a7c5f2035426b9158007bb28 (diff) | |
download | pki-2119f1b218e9d68b13496e7042785d9c68753966.tar.gz pki-2119f1b218e9d68b13496e7042785d9c68753966.tar.xz pki-2119f1b218e9d68b13496e7042785d9c68753966.zip |
Reorganized server packages.
The tomcat, cms, and cmscore packages have been moved from base/common
into separate folders in base/server so that they can be built separately.
Diffstat (limited to 'base/server/cms/src/com/netscape/cms/servlet/processors')
7 files changed, 2885 insertions, 0 deletions
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/CMCProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/CMCProcessor.java new file mode 100644 index 000000000..3c5c4080b --- /dev/null +++ b/base/server/cms/src/com/netscape/cms/servlet/processors/CMCProcessor.java @@ -0,0 +1,407 @@ +// --- 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.processors; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.PublicKey; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Hashtable; + +import netscape.security.pkcs.PKCS10; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import org.mozilla.jss.asn1.ANY; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.crypto.DigestAlgorithm; +import org.mozilla.jss.pkcs10.CertificationRequest; +import org.mozilla.jss.pkcs11.PK11PubKey; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.pkix.cert.CertificateInfo; +import org.mozilla.jss.pkix.cmc.PKIData; +import org.mozilla.jss.pkix.cmc.TaggedAttribute; +import org.mozilla.jss.pkix.cmc.TaggedCertificationRequest; +import org.mozilla.jss.pkix.cmc.TaggedRequest; +import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo; +import org.mozilla.jss.pkix.cms.IssuerAndSerialNumber; +import org.mozilla.jss.pkix.cms.SignedData; +import org.mozilla.jss.pkix.cms.SignerIdentifier; +import org.mozilla.jss.pkix.crmf.CertReqMsg; +import org.mozilla.jss.pkix.crmf.CertRequest; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.pkix.primitive.Name; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.common.ICMSRequest; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Process CMC messages according to RFC 2797 + * See http://www.ietf.org/rfc/rfc2797.txt + * + * @version $Revision$, $Date$ + */ +public class CMCProcessor extends PKIProcessor { + + private boolean enforcePop = false; + + public CMCProcessor() { + super(); + } + + public CMCProcessor(ICMSRequest cmsReq, CMSServlet servlet, boolean doEnforcePop) { + + super(cmsReq, servlet); + enforcePop = doEnforcePop; + + } + + public void process(ICMSRequest cmsReq) + throws EBaseException { + } + + public void fillCertInfo( + String protocolString, X509CertInfo certInfo, + IAuthToken authToken, IArgBlock httpParams) + throws EBaseException { + } + + public X509CertInfo[] fillCertInfoArray( + String protocolString, IAuthToken authToken, IArgBlock httpParams, IRequest req) + throws EBaseException { + + CMS.debug("CMCProcessor: In CMCProcessor.fillCertInfoArray!"); + String cmc = protocolString; + + try { + byte[] cmcBlob = CMS.AtoB(cmc); + ByteArrayInputStream cmcBlobIn = + new ByteArrayInputStream(cmcBlob); + + org.mozilla.jss.pkix.cms.ContentInfo cmcReq = (org.mozilla.jss.pkix.cms.ContentInfo) + org.mozilla.jss.pkix.cms.ContentInfo.getTemplate().decode(cmcBlobIn); + + if (!cmcReq.getContentType().equals(org.mozilla.jss.pkix.cms.ContentInfo.SIGNED_DATA) + || !cmcReq.hasContent()) + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_CMC_CONTENT")); + + SignedData cmcFullReq = (SignedData) + cmcReq.getInterpretedContent(); + + EncapsulatedContentInfo ci = cmcFullReq.getContentInfo(); + + OBJECT_IDENTIFIER id = ci.getContentType(); + + if (!id.equals(OBJECT_IDENTIFIER.id_cct_PKIData) || !ci.hasContent()) { + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_NO_PKIDATA")); + } + OCTET_STRING content = ci.getContent(); + + ByteArrayInputStream s = new ByteArrayInputStream(content.toByteArray()); + PKIData pkiData = (PKIData) (new PKIData.Template()).decode(s); + + SEQUENCE reqSequence = pkiData.getReqSequence(); + + int numReqs = reqSequence.size(); + X509CertInfo[] certInfoArray = new X509CertInfo[numReqs]; + String[] reqIdArray = new String[numReqs]; + + for (int i = 0; i < numReqs; i++) { + // decode message. + TaggedRequest taggedRequest = (TaggedRequest) reqSequence.elementAt(i); + + TaggedRequest.Type type = taggedRequest.getType(); + + if (type.equals(TaggedRequest.PKCS10)) { + TaggedCertificationRequest tcr = taggedRequest.getTcr(); + int p10Id = tcr.getBodyPartID().intValue(); + + reqIdArray[i] = String.valueOf(p10Id); + + CertificationRequest p10 = + tcr.getCertificationRequest(); + + // transfer to sun class + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + + p10.encode(ostream); + + PKCS10Processor pkcs10Processor = new PKCS10Processor(mRequest, mServlet); + + try { + PKCS10 pkcs10 = new PKCS10(ostream.toByteArray()); + //xxx do we need to do anything else? + X509CertInfo certInfo = CMS.getDefaultX509CertInfo(); + + pkcs10Processor.fillCertInfo(pkcs10, certInfo, authToken, httpParams); + + /* fillPKCS10(pkcs10,certInfo, + authToken, httpParams); + */ + + certInfoArray[i] = certInfo; + } catch (Exception e) { + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_PKCS10_ERROR", e.toString())); + } + } else if (type.equals(TaggedRequest.CRMF)) { + + CRMFProcessor crmfProc = new CRMFProcessor(mRequest, mServlet, enforcePop); + + CertReqMsg crm = taggedRequest.getCrm(); + CertRequest certReq = crm.getCertReq(); + + INTEGER certReqId = certReq.getCertReqId(); + int srcId = certReqId.intValue(); + + reqIdArray[i] = String.valueOf(srcId); + + certInfoArray[i] = crmfProc.processIndividualRequest(crm, authToken, httpParams); + + } else { + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_CMC_CONTENT")); + } + } + + // verify the signerInfo + SET dais = cmcFullReq.getDigestAlgorithmIdentifiers(); + int numDig = dais.size(); + Hashtable<String, byte[]> digs = new Hashtable<String, byte[]>(); + + for (int i = 0; i < numDig; i++) { + AlgorithmIdentifier dai = + (AlgorithmIdentifier) dais.elementAt(i); + String name = + DigestAlgorithm.fromOID(dai.getOID()).toString(); + + MessageDigest md = + MessageDigest.getInstance(name); + + byte[] digest = md.digest(content.toByteArray()); + + digs.put(name, digest); + } + + SET sis = cmcFullReq.getSignerInfos(); + int numSis = sis.size(); + + for (int i = 0; i < numSis; i++) { + org.mozilla.jss.pkix.cms.SignerInfo si = + (org.mozilla.jss.pkix.cms.SignerInfo) + sis.elementAt(i); + + String name = si.getDigestAlgorithm().toString(); + byte[] digest = digs.get(name); + + if (digest == null) { + MessageDigest md = MessageDigest.getInstance(name); + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + + pkiData.encode(ostream); + digest = md.digest(ostream.toByteArray()); + + } + + SignerIdentifier sid = si.getSignerIdentifier(); + + if (sid.getType().equals(SignerIdentifier.ISSUER_AND_SERIALNUMBER)) { + IssuerAndSerialNumber issuerAndSerialNumber = sid.getIssuerAndSerialNumber(); + // find from the certs in the signedData + X509Certificate cert = null; + + if (cmcFullReq.hasCertificates()) { + SET certs = cmcFullReq.getCertificates(); + int numCerts = certs.size(); + + for (int j = 0; j < numCerts; j++) { + Certificate certJss = + (Certificate) certs.elementAt(j); + CertificateInfo certI = + certJss.getInfo(); + Name issuer = certI.getIssuer(); + byte[] issuerB = ASN1Util.encode(issuer); + + INTEGER sn = certI.getSerialNumber(); + + if (new String(issuerB).equals(new + String(ASN1Util.encode(issuerAndSerialNumber.getIssuer()))) + && sn.toString().equals(issuerAndSerialNumber.getSerialNumber().toString())) { + ByteArrayOutputStream os = new + ByteArrayOutputStream(); + + certJss.encode(os); + cert = new X509CertImpl(os.toByteArray()); + // xxx validate the cert length + + } + } + + } + // find from internaldb if it's ca. (ra does not have that.) + // find from internaldb usrgrp info + + if (cert == null) { + // find from certDB + si.verify(digest, id); + } else { + PublicKey signKey = cert.getPublicKey(); + PK11PubKey pubK = PK11PubKey.fromSPKI(((X509Key) signKey).getKey()); + si.verify(digest, id, pubK); + } + + } else { + OCTET_STRING ski = sid.getSubjectKeyIdentifier(); + // find the publicKey using ski + int j = 0; + PublicKey signKey = null; + + while (signKey == null && j < numReqs) { + X509Key subjectKeyInfo = + (X509Key) ((CertificateX509Key) certInfoArray[j].get(X509CertInfo.KEY)) + .get(CertificateX509Key.KEY); + MessageDigest md = MessageDigest.getInstance("SHA-1"); + + md.update(subjectKeyInfo.getEncoded()); + byte[] skib = md.digest(); + + if (new String(skib).equals(new String(ski.toByteArray()))) { + signKey = subjectKeyInfo; + } + j++; + } + if (signKey == null) { + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_CMC_ERROR", + "SubjectKeyIdentifier in SignerInfo does not match any publicKey in the request.")); + } else { + PK11PubKey pubK = PK11PubKey.fromSPKI(((X509Key) signKey).getKey()); + si.verify(digest, id, pubK); + } + } + } + // end verify signerInfo + + // Get control sequence + // verisign has transactionId, senderNonce, regInfo + // identification, identityproof + SEQUENCE controls = pkiData.getControlSequence(); + int numControls = controls.size(); + + for (int i = 0; i < numControls; i++) { + TaggedAttribute control = + (TaggedAttribute) controls.elementAt(i); + OBJECT_IDENTIFIER type = control.getType(); + SET values = control.getValues(); + int numVals = values.size(); + + if (type.equals(OBJECT_IDENTIFIER.id_cmc_transactionId)) { + String[] vals = null; + + if (numVals > 0) + vals = new String[numVals]; + for (int j = 0; j < numVals; j++) { + ANY val = (ANY) + values.elementAt(j); + INTEGER transId = (INTEGER) val.decodeWith( + INTEGER.getTemplate()); + + if (transId != null) { + vals[j] = transId.toString(); + } + } + if (vals != null) + req.setExtData(IRequest.CMC_TRANSID, vals); + } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_senderNonce)) { + String[] vals = null; + + if (numVals > 0) + vals = new String[numVals]; + for (int j = 0; j < numVals; j++) { + ANY val = (ANY) + values.elementAt(j); + OCTET_STRING nonce = (OCTET_STRING) + val.decodeWith(OCTET_STRING.getTemplate()); + + if (nonce != null) { + vals[j] = new String(nonce.toByteArray()); + } + } + if (vals != null) + req.setExtData(IRequest.CMC_SENDERNONCE, vals); + + } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_regInfo)) { + // what can we do here + // for verisign, we just debug.print() + } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_identification)) { + // what can we do here + // for verisign, we just debug.print() + } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_identityProof)) { + // what can we do here + // for verisign, we just debug.print() + } + } + + req.setExtData(IRequest.CMC_REQIDS, reqIdArray); + return certInfoArray; + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CMC_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CMC_TO_CERTINFO_ERROR")); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CMC_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CMC_TO_CERTINFO_ERROR")); + } catch (InvalidBERException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CMC_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CMC_TO_CERTINFO_ERROR")); + } catch (InvalidKeyException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CMC_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CMC_TO_CERTINFO_ERROR")); + } catch (Exception e) { + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CMC_ERROR", e.toString())); + } + + } + +} diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/CRMFProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/CRMFProcessor.java new file mode 100644 index 000000000..1da0cf3c4 --- /dev/null +++ b/base/server/cms/src/com/netscape/cms/servlet/processors/CRMFProcessor.java @@ -0,0 +1,373 @@ +// --- 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.processors; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.cert.CertificateException; + +import netscape.security.util.ObjectIdentifier; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.CertificateVersion; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.Extension; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.pkix.crmf.CertReqMsg; +import org.mozilla.jss.pkix.crmf.CertRequest; +import org.mozilla.jss.pkix.crmf.CertTemplate; +import org.mozilla.jss.pkix.crmf.ProofOfPossession; +import org.mozilla.jss.pkix.primitive.Name; +import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.common.ICMSRequest; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Process CRMF requests, according to RFC 2511 + * See http://www.ietf.org/rfc/rfc2511.txt + * + * @version $Revision$, $Date$ + */ +public class CRMFProcessor extends PKIProcessor { + + @SuppressWarnings("unused") + private ICMSRequest mRequest; + + private boolean enforcePop = false; + + private final static String LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION = + "LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION_2"; + + public CRMFProcessor() { + super(); + } + + public CRMFProcessor(ICMSRequest cmsReq, CMSServlet servlet, boolean doEnforcePop) { + super(cmsReq, servlet); + + enforcePop = doEnforcePop; + mRequest = cmsReq; + } + + public void process(ICMSRequest cmsReq) + throws EBaseException { + } + + /** + * Verify Proof of Possession (POP) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION used when proof of possession is checked during + * certificate enrollment + * </ul> + * + * @param certReqMsg the certificate request message + * @exception EBaseException an error has occurred + */ + private void verifyPOP(CertReqMsg certReqMsg) + throws EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + try { + CMS.debug("CRMFProcessor: verifyPOP"); + + if (certReqMsg.hasPop()) { + ProofOfPossession pop = certReqMsg.getPop(); + + ProofOfPossession.Type popType = pop.getType(); + + if (popType == ProofOfPossession.SIGNATURE) { + CMS.debug("CRMFProcessor: Request has pop."); + try { + certReqMsg.verify(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION, + auditSubjectID, + ILogger.SUCCESS); + + audit(auditMessage); + } catch (Exception e) { + CMS.debug("CRMFProcessor: Failed POP verify!"); + + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_POP_VERIFY")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_POP_VERIFY")); + } + } + } else { + if (enforcePop == true) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_NO_POP")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_NO_POP")); + } + } + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + } + } + + public X509CertInfo processIndividualRequest(CertReqMsg certReqMsg, IAuthToken authToken, IArgBlock httpParams) + throws EBaseException { + CMS.debug("CRMFProcessor::processIndividualRequest!"); + + try { + + verifyPOP(certReqMsg); + + CertRequest certReq = certReqMsg.getCertReq(); + + CertTemplate certTemplate = certReq.getCertTemplate(); + X509CertInfo certInfo = CMS.getDefaultX509CertInfo(); + + // get key + SubjectPublicKeyInfo spki = certTemplate.getPublicKey(); + ByteArrayOutputStream keyout = new ByteArrayOutputStream(); + + spki.encode(keyout); + byte[] keybytes = keyout.toByteArray(); + X509Key key = new X509Key(); + + key.decode(keybytes); + certInfo.set(X509CertInfo.KEY, new CertificateX509Key(key)); + + // field suggested notBefore and notAfter in CRMF + // Tech Support #383184 + if (certTemplate.getNotBefore() != null || certTemplate.getNotAfter() != null) { + CertificateValidity certValidity = + new CertificateValidity(certTemplate.getNotBefore(), certTemplate.getNotAfter()); + + certInfo.set(X509CertInfo.VALIDITY, certValidity); + } + + if (certTemplate.hasSubject()) { + Name subjectdn = certTemplate.getSubject(); + ByteArrayOutputStream subjectEncStream = + new ByteArrayOutputStream(); + + subjectdn.encode(subjectEncStream); + byte[] subjectEnc = subjectEncStream.toByteArray(); + X500Name subject = new X500Name(subjectEnc); + + certInfo.set(X509CertInfo.SUBJECT, + new CertificateSubjectName(subject)); + } else if (authToken == null || + authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) == null) { + // No subject name - error! + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN")); + } + + // get extensions + CertificateExtensions extensions = null; + + try { + extensions = (CertificateExtensions) + certInfo.get(X509CertInfo.EXTENSIONS); + } catch (CertificateException e) { + extensions = null; + } catch (IOException e) { + extensions = null; + } + if (certTemplate.hasExtensions()) { + // put each extension from CRMF into CertInfo. + // index by extension name, consistent with + // CertificateExtensions.parseExtension() method. + if (extensions == null) + extensions = new CertificateExtensions(); + int numexts = certTemplate.numExtensions(); + + for (int j = 0; j < numexts; j++) { + org.mozilla.jss.pkix.cert.Extension jssext = + certTemplate.extensionAt(j); + boolean isCritical = jssext.getCritical(); + org.mozilla.jss.asn1.OBJECT_IDENTIFIER jssoid = + jssext.getExtnId(); + long[] numbers = jssoid.getNumbers(); + int[] oidNumbers = new int[numbers.length]; + + for (int k = numbers.length - 1; k >= 0; k--) { + oidNumbers[k] = (int) numbers[k]; + } + ObjectIdentifier oid = + new ObjectIdentifier(oidNumbers); + org.mozilla.jss.asn1.OCTET_STRING jssvalue = + jssext.getExtnValue(); + ByteArrayOutputStream jssvalueout = + new ByteArrayOutputStream(); + + jssvalue.encode(jssvalueout); + byte[] extValue = jssvalueout.toByteArray(); + + Extension ext = + new Extension(oid, isCritical, extValue); + + extensions.parseExtension(ext); + } + + certInfo.set(X509CertInfo.VERSION, + new CertificateVersion(CertificateVersion.V3)); + certInfo.set(X509CertInfo.EXTENSIONS, extensions); + + } + + // Added a new configuration parameter + // eeGateway.Enrollment.authTokenOverride=[true|false] + // By default, it is set to true. In most + // of the case, administrator would want + // to have the control of the subject name + // formulation. + // -- CRMFfillCert + if (authToken != null && + authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) != null) { + // if authenticated override subect name, validity and + // extensions if any from authtoken. + fillCertInfoFromAuthToken(certInfo, authToken); + } + + // SPECIAL CASE: + // if it is adminEnroll servlet, get the validity + // from the http parameters. + if (mServletId.equals(PKIProcessor.ADMIN_ENROLL_SERVLET_ID)) { + fillValidityFromForm(certInfo, httpParams); + } + + return certInfo; + + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR")); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR")); + } /* catch (InvalidBERException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1",e.toString())); + throw new ECMSGWException( + CMSGWResources.ERROR_CRMF_TO_CERTINFO); + } */catch (InvalidKeyException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR")); + } + + } + + public X509CertInfo[] fillCertInfoArray( + String protocolString, IAuthToken authToken, IArgBlock httpParams, IRequest req) + throws EBaseException { + + CMS.debug("CRMFProcessor.fillCertInfoArray!"); + + String crmf = protocolString; + + try { + byte[] crmfBlob = CMS.AtoB(crmf); + ByteArrayInputStream crmfBlobIn = + new ByteArrayInputStream(crmfBlob); + + SEQUENCE crmfMsgs = (SEQUENCE) + new SEQUENCE.OF_Template(new CertReqMsg.Template()).decode(crmfBlobIn); + + int nummsgs = crmfMsgs.size(); + X509CertInfo[] certInfoArray = new X509CertInfo[nummsgs]; + + for (int i = 0; i < nummsgs; i++) { + // decode message. + CertReqMsg certReqMsg = (CertReqMsg) crmfMsgs.elementAt(i); + + CertRequest certReq = certReqMsg.getCertReq(); + INTEGER certReqId = certReq.getCertReqId(); + int srcId = certReqId.intValue(); + + req.setExtData(IRequest.CRMF_REQID, String.valueOf(srcId)); + + certInfoArray[i] = processIndividualRequest(certReqMsg, authToken, httpParams); + + } + + //do_testbed_hack(nummsgs, certInfoArray, httpParams); + + return certInfoArray; + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR")); + } catch (InvalidBERException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR")); + } + } +} diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/IPKIProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/IPKIProcessor.java new file mode 100644 index 000000000..3fd42db08 --- /dev/null +++ b/base/server/cms/src/com/netscape/cms/servlet/processors/IPKIProcessor.java @@ -0,0 +1,33 @@ +// --- 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.processors; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.common.ICMSRequest; + +/** + * This represents the request parser. + * + * @version $Revision$, $Date$ + */ +public interface IPKIProcessor { + + public void process(ICMSRequest cmsReq) + throws EBaseException; + +} diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/KeyGenProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/KeyGenProcessor.java new file mode 100644 index 000000000..d3f8ba655 --- /dev/null +++ b/base/server/cms/src/com/netscape/cms/servlet/processors/KeyGenProcessor.java @@ -0,0 +1,120 @@ +// --- 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.processors; + +import java.io.IOException; +import java.security.cert.CertificateException; + +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.KeyGenInfo; +import com.netscape.certsrv.common.ICMSRequest; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * KeyGenProcess parses Certificate request matching the + * KEYGEN tag format used by Netscape Communicator 4.x + * + * @version $Revision$, $Date$ + */ +public class KeyGenProcessor extends PKIProcessor { + + public KeyGenProcessor() { + super(); + } + + public KeyGenProcessor(ICMSRequest cmsReq, CMSServlet servlet) { + super(cmsReq, servlet); + + } + + public void process(ICMSRequest cmsReq) + throws EBaseException { + } + + public void fillCertInfo( + String protocolString, X509CertInfo certInfo, + IAuthToken authToken, IArgBlock httpParams) + throws EBaseException { + + CMS.debug("KeyGenProcessor: fillCertInfo"); + + if (mServlet == null) { + return; + } + + KeyGenInfo keyGenInfo = httpParams.getValueAsKeyGenInfo( + PKIProcessor.SUBJECT_KEYGEN_INFO, null); + + // fill key + X509Key key = null; + + key = keyGenInfo.getSPKI(); + if (key == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_MISSING_KEY_IN_KEYGENINFO")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_KEY_IN_KEYGENINFO")); + } + try { + certInfo.set(X509CertInfo.KEY, new CertificateX509Key(key)); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + "Could not set key into certInfo from keygen. Error " + e); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_KEYGEN_FAILED", e.toString())); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_KEYGEN_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_KEYGEN_FAILED", e.toString())); + } + + String authMgr = mServlet.getAuthMgr(); + + // if not authenticated, fill subject name, validity & extensions + // from authtoken. + if (authToken == null) { + fillCertInfoFromForm(certInfo, httpParams); + } else { + if (authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) == null) { + // allow special case for agent gateway in admin enroll + // and bulk issuance. + if (!authMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID) && + !authMgr.equals(IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID)) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN")); + } + fillCertInfoFromForm(certInfo, httpParams); + } else { + fillCertInfoFromAuthToken(certInfo, authToken); + } + } + } +} diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/PKCS10Processor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/PKCS10Processor.java new file mode 100644 index 000000000..184216972 --- /dev/null +++ b/base/server/cms/src/com/netscape/cms/servlet/processors/PKCS10Processor.java @@ -0,0 +1,285 @@ +// --- 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.processors; + +import java.io.IOException; +import java.security.cert.CertificateException; + +import netscape.security.pkcs.PKCS10; +import netscape.security.pkcs.PKCS10Attribute; +import netscape.security.pkcs.PKCS10Attributes; +import netscape.security.pkcs.PKCS9Attribute; +import netscape.security.util.DerInputStream; +import netscape.security.util.DerOutputStream; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.Extensions; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.common.ICMSRequest; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * PKCS10Processor process Certificate Requests in + * PKCS10 format, as defined here: + * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-10/index.html + * + * @version $Revision$, $Date$ + */ +public class PKCS10Processor extends PKIProcessor { + + private PKCS10 mPkcs10 = null; + + private final String USE_INTERNAL_PKCS10 = "internal"; + + public PKCS10Processor() { + + super(); + } + + public PKCS10Processor(ICMSRequest cmsReq, CMSServlet servlet) { + super(cmsReq, servlet); + + } + + public void process(ICMSRequest cmsReq) + throws EBaseException { + } + + public void fillCertInfo( + PKCS10 pkcs10, X509CertInfo certInfo, + IAuthToken authToken, IArgBlock httpParams) + throws EBaseException { + + mPkcs10 = pkcs10; + + fillCertInfo(USE_INTERNAL_PKCS10, certInfo, authToken, httpParams); + + } + + public void fillCertInfo( + String protocolString, X509CertInfo certInfo, + IAuthToken authToken, IArgBlock httpParams) + throws EBaseException { + + PKCS10 p10 = null; + + CMS.debug("PKCS10Processor:fillCertInfo"); + + if (protocolString == null) { + p10 = getPKCS10(httpParams); + } else if (protocolString.equals(USE_INTERNAL_PKCS10)) { + p10 = mPkcs10; + } else { + CMS.debug("PKCS10Processor::fillCertInfo() - p10 is null!"); + throw new EBaseException("p10 is null"); + } + + if (mServlet == null) { + EBaseException ex = new ECMSGWException("Servlet property of PKCS10Processor is null."); + + throw ex; + + } + + // fill key + X509Key key = p10.getSubjectPublicKeyInfo(); + + if (key == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_MISSING_KEY_IN_P10")); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_MISSING_KEY_IN_P10")); + } + CertificateX509Key certKey = new CertificateX509Key(key); + + try { + certInfo.set(X509CertInfo.KEY, certKey); + } catch (CertificateException e) { + EBaseException ex = new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString())); + + log(ILogger.LL_FAILURE, ex.toString()); + throw ex; + } catch (IOException e) { + EBaseException ex = new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString())); + + log(ILogger.LL_FAILURE, ex.toString()); + throw ex; + } + + X500Name subject = p10.getSubjectName(); + + if (subject != null) { + try { + certInfo.set(X509CertInfo.SUBJECT, + new CertificateSubjectName(subject)); + log(ILogger.LL_INFO, + "Setting subject name " + subject + " from p10."); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_SUBJECT_FROM_P10", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_FROM_P10_FAILED", e.toString())); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_SUBJECT_FROM_P10", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_FROM_P10_FAILED", e.toString())); + } catch (Exception e) { + // if anything bad happens in X500 name parsing, + // this will catch it. + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_SUBJECT_FROM_P10", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_FROM_P10_FAILED", e.toString())); + } + } else if (authToken == null || + authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_SUBJECT_IN_P10")); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_MISSING_SUBJECT_IN_P10")); + } + + // fill extensions from pkcs 10 attributes if any. + // other pkcs10 attributes are not recognized. + // ExtensionReq ::= SEQUENCE OF Extension + // ExtensionReq {pkcs-9 14}. + try { + PKCS10Attributes p10Attrs = p10.getAttributes(); + + if (p10Attrs != null) { + PKCS10Attribute p10Attr = p10Attrs.getAttribute(CertificateExtensions.NAME); + + if (p10Attr != null && p10Attr.getAttributeId().equals( + PKCS9Attribute.EXTENSION_REQUEST_OID)) { + Extensions exts0 = (Extensions) p10Attr.getAttributeValue(); + DerOutputStream extOut = new DerOutputStream(); + + exts0.encode(extOut); + byte[] extB = extOut.toByteArray(); + DerInputStream extIn = new DerInputStream(extB); + CertificateExtensions exts = new CertificateExtensions(extIn); + + if (exts != null) { + certInfo.set(X509CertInfo.EXTENSIONS, exts); + } + } + } + CMS.debug( + "PKCS10Processor: Seted cert extensions from pkcs10. "); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_EXTENSIONS_FROM_P10", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString())); + + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_EXTENSIONS_FROM_P10", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString())); + } catch (Exception e) { + // if anything bad happens in extensions parsing, + // this will catch it. + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_EXTENSIONS_FROM_P10", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString())); + } + + // override pkcs10 attributes with authtoken attributes + // like subject name, validity and extensions if any. + // adminEnroll is an exception + String authMgr = mServlet.getAuthMgr(); + + if (authToken != null && + authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) != null && + !(authMgr.equals(IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID))) { + fillCertInfoFromAuthToken(certInfo, authToken); + } + + // SPECIAL CASE: + // if it is adminEnroll servlet, get the validity + // from the http parameters. + if (mServletId.equals(PKIProcessor.ADMIN_ENROLL_SERVLET_ID)) { + fillValidityFromForm(certInfo, httpParams); + } + + } + + private PKCS10 getPKCS10(IArgBlock httpParams) + throws EBaseException { + + PKCS10 pkcs10 = null; + + String certType = null; + + // support Enterprise 3.5.1 server where CERT_TYPE=csrCertType + // instead of certType + certType = httpParams.getValueAsString(PKIProcessor.OLD_CERT_TYPE, null); + if (certType == null) { + certType = httpParams.getValueAsString(PKIProcessor.CERT_TYPE, "client"); + } else { + // some policies may rely on the fact that + // CERT_TYPE is set. So for 3.5.1 or eariler + // we need to set CERT_TYPE but not here. + } + if (certType.equals("client")) { + // coming from MSIE + String p10b64 = httpParams.getValueAsString(PKIProcessor.PKCS10_REQUEST, null); + + if (p10b64 != null) { + try { + byte[] bytes = CMS.AtoB(p10b64); + + pkcs10 = new PKCS10(bytes); + } catch (Exception e) { + // ok, if the above fails, it could + // be a PKCS10 with header + pkcs10 = httpParams.getValueAsPKCS10(PKIProcessor.PKCS10_REQUEST, false, null); + // e.printStackTrace(); + } + } + + //pkcs10 = httpParams.getValuePKCS10(PKCS10_REQUEST, null); + + } else { + try { + // coming from server cut & paste blob. + pkcs10 = httpParams.getValueAsPKCS10(PKIProcessor.PKCS10_REQUEST, false, null); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + return pkcs10; + + } + +} diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/PKIProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/PKIProcessor.java new file mode 100644 index 000000000..bea899368 --- /dev/null +++ b/base/server/cms/src/com/netscape/cms/servlet/processors/PKIProcessor.java @@ -0,0 +1,355 @@ +// --- 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.processors; + +import java.io.IOException; +import java.security.cert.CertificateException; +import java.util.Date; + +import javax.servlet.http.HttpServletRequest; + +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.common.ICMSRequest; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Process Certificate Requests + * + * @version $Revision$, $Date$ + */ +public class PKIProcessor implements IPKIProcessor { + + public final static String ADMIN_ENROLL_SERVLET_ID = "caadminEnroll"; + public static final String SUBJECT_NAME = "subject"; + public static final String OLD_CERT_TYPE = "csrCertType"; + public static final String CERT_TYPE = "certType"; + public static final String PKCS10_REQUEST = "pkcs10Request"; + public static final String SUBJECT_KEYGEN_INFO = "subjectKeyGenInfo"; + + protected ICMSRequest mRequest = null; + + protected HttpServletRequest httpReq = null; + protected String mServletId = null; + protected CMSServlet mServlet = null; + + protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger(); + + public PKIProcessor() { + } + + public PKIProcessor(ICMSRequest cmsReq, CMSServlet servlet) { + mRequest = cmsReq; + + mServlet = servlet; + + if (mServlet == null || mRequest == null) { + return; + } + + mServletId = servlet.getId(); + + } + + public void process(ICMSRequest cmsReq) + throws EBaseException { + } + + protected void fillCertInfo( + String protocolString, X509CertInfo certInfo, + IAuthToken authToken, IArgBlock httpParams) + throws EBaseException { + } + + protected X509CertInfo[] fillCertInfoArray( + String protocolString, IAuthToken authToken, IArgBlock httpParams, IRequest req) + throws EBaseException { + return null; + } + + /** + * fill subject name, validity, extensions from authoken if any, + * overriding what was in pkcs10. + * fill subject name, extensions from http input if not authenticated. + * requests not authenticated will need to be approved by an agent. + */ + public static void fillCertInfoFromAuthToken( + X509CertInfo certInfo, IAuthToken authToken) + throws EBaseException { + // override subject, validity and extensions from auth token + // CA determines algorithm, version and issuer. + // take key from keygen, cmc, pkcs10 or crmf. + + CMS.debug("PKIProcessor: fillCertInfoFromAuthToken"); + // subject name. + try { + String subjectname = + authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT); + + if (subjectname != null) { + CertificateSubjectName certSubject = new CertificateSubjectName(new X500Name(subjectname)); + + certInfo.set(X509CertInfo.SUBJECT, certSubject); + log(ILogger.LL_INFO, + "cert subject set to " + certSubject + " from authtoken"); + } + } catch (CertificateException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", + e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR")); + } catch (IOException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME", + e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR")); + } + + // validity + try { + CertificateValidity validity = null; + Date notBefore = + authToken.getInDate(AuthToken.TOKEN_CERT_NOTBEFORE); + Date notAfter = + authToken.getInDate(AuthToken.TOKEN_CERT_NOTAFTER); + + if (notBefore != null && notAfter != null) { + validity = new CertificateValidity(notBefore, notAfter); + certInfo.set(X509CertInfo.VALIDITY, validity); + log(ILogger.LL_INFO, + "cert validity set to " + validity + " from authtoken"); + } + } catch (CertificateException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_VALIDITY_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_VALIDITY_ERROR")); + } catch (IOException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_VALIDITY_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_VALIDITY_ERROR")); + } + + // extensions + try { + CertificateExtensions extensions = + authToken.getInCertExts(X509CertInfo.EXTENSIONS); + + if (extensions != null) { + certInfo.set(X509CertInfo.EXTENSIONS, extensions); + log(ILogger.LL_INFO, "cert extensions set from authtoken"); + } + } catch (CertificateException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_EXTENSIONS_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_EXTENSIONS_ERROR")); + } catch (IOException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_EXTENSIONS_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_EXTENSIONS_ERROR")); + } + } + + /** + * fill subject name, extension from form. + * this is done for unauthenticated requests. + * unauthenticated requests must be approved by agents so these will + * all be seen by and agent. + */ + public static void fillCertInfoFromForm( + X509CertInfo certInfo, IArgBlock httpParams) + throws EBaseException { + + CMS.debug("PKIProcessor: fillCertInfoFromForm"); + // subject name. + try { + String subject = httpParams.getValueAsString(PKIProcessor.SUBJECT_NAME, null); + + if (subject == null) { + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_SUBJECT_FROM_FORM")); + } + + X500Name x500name = new X500Name(subject); + + certInfo.set( + X509CertInfo.SUBJECT, new CertificateSubjectName(x500name)); + + fillValidityFromForm(certInfo, httpParams); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR")); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR")); + } catch (IllegalArgumentException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString())); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_REQ_ILLEGAL_CHARACTERS")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CONVERT_DN_TO_X500NAME_ERROR")); + } + + // requested extensions. + // let polcies form extensions from http input. + } + + public static void fillValidityFromForm( + X509CertInfo certInfo, IArgBlock httpParams) + throws EBaseException { + CMS.debug("PKIProcessor: fillValidityFromForm!"); + try { + String notValidBeforeStr = httpParams.getValueAsString("notValidBefore", null); + String notValidAfterStr = httpParams.getValueAsString("notValidAfter", null); + + if (notValidBeforeStr != null && notValidAfterStr != null) { + long notValidBefore = 0; + long notValidAfter = 0; + + try { + notValidBefore = Long.parseLong(notValidBeforeStr); + } catch (NumberFormatException e) { + } + try { + notValidAfter = Long.parseLong(notValidAfterStr); + } catch (NumberFormatException e) { + } + + if (notValidBefore > 0 && notValidAfter > 0) { + CertificateValidity validity = null; + Date notBefore = new Date(notValidBefore); + Date notAfter = new Date(notValidAfter); + + if (notBefore != null && notAfter != null) { + validity = new CertificateValidity(notBefore, notAfter); + certInfo.set(X509CertInfo.VALIDITY, validity); + log(ILogger.LL_INFO, + "cert validity set to " + validity + " from authtoken"); + } + } + } + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR")); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR")); + } + } + + /** + * log according to authority category. + */ + public static void log(int event, int level, String msg) { + CMS.getLogger().log(event, ILogger.S_OTHER, level, + "PKIProcessor " + ": " + msg); + } + + public static void log(int level, String msg) { + CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER, level, + "PKIProcessor " + ": " + msg); + } + + /** + * Signed Audit Log + * + * This method is inherited by all extended "CMSServlet"s, + * and is called to store messages to the signed audit log. + * <P> + * + * @param msg signed audit log message + */ + protected void audit(String msg) { + // in this case, do NOT strip preceding/trailing whitespace + // from passed-in String parameters + + if (mSignedAuditLogger == null) { + return; + } + + mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT, + null, + ILogger.S_SIGNED_AUDIT, + ILogger.LL_SECURITY, + msg); + } + + /** + * Signed Audit Log Subject ID + * + * This method is inherited by all extended "CMSServlet"s, + * and is called to obtain the "SubjectID" for + * a signed audit log message. + * <P> + * + * @return id string containing the signed audit log message SubjectID + */ + protected String auditSubjectID() { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String subjectID = null; + + // Initialize subjectID + SessionContext auditContext = SessionContext.getExistingContext(); + + if (auditContext != null) { + subjectID = (String) + auditContext.get(SessionContext.USER_ID); + + if (subjectID != null) { + subjectID = subjectID.trim(); + } else { + subjectID = ILogger.NONROLEUSER; + } + } else { + subjectID = ILogger.UNIDENTIFIED; + } + + return subjectID; + } +} diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/Processor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/Processor.java new file mode 100644 index 000000000..5a3b27063 --- /dev/null +++ b/base/server/cms/src/com/netscape/cms/servlet/processors/Processor.java @@ -0,0 +1,1312 @@ +// --- 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) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package com.netscape.cms.servlet.processors; + +import java.lang.reflect.Method; +import java.math.BigInteger; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.StringTokenizer; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.FormParam; + +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.IAuthzSubsystem; +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.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.MetaInfo; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.IAuditor; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileAuthenticator; +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; +import com.netscape.cms.servlet.common.AuthCredentials; +import com.netscape.cms.servlet.common.CMSGateway; +import com.netscape.cms.servlet.common.ServletUtils; +import com.netscape.cmsutil.util.Utils; + +public class Processor { + + public final static String ARG_AUTH_TOKEN = "auth_token"; + public final static String ARG_REQUEST_OWNER = "requestOwner"; + public final static String HDR_LANG = "accept-language"; + public final static String ARG_PROFILE = "profile"; + public final static String ARG_REQUEST_NOTES = "requestNotes"; + public final static String ARG_PROFILE_ID = "profileId"; + public final static String ARG_RENEWAL_PROFILE_ID = "rprofileId"; + public final static String ARG_PROFILE_IS_ENABLED = "profileIsEnable"; + public final static String ARG_PROFILE_IS_VISIBLE = "profileIsVisible"; + public final static String ARG_PROFILE_ENABLED_BY = "profileEnableBy"; + public final static String ARG_PROFILE_APPROVED_BY = "profileApprovedBy"; + public final static String ARG_PROFILE_NAME = "profileName"; + public final static String ARG_PROFILE_DESC = "profileDesc"; + public final static String ARG_PROFILE_REMOTE_HOST = "profileRemoteHost"; + public final static String ARG_PROFILE_REMOTE_ADDR = "profileRemoteAddr"; + public final static String ARG_PROFILE_SET_ID = "profileSetId"; + public final static String ARG_OUTPUT_LIST = "outputList"; + public final static String ARG_OUTPUT_ID = "outputId"; + public final static String ARG_OUTPUT_SYNTAX = "outputSyntax"; + public final static String ARG_OUTPUT_CONSTRAINT = "outputConstraint"; + public final static String ARG_OUTPUT_NAME = "outputName"; + public final static String ARG_OUTPUT_VAL = "outputVal"; + public final static String ARG_REQUEST_LIST = "requestList"; + public final static String ARG_REQUEST_ID = "requestId"; + public final static String ARG_REQUEST_TYPE = "requestType"; + public final static String ARG_REQUEST_STATUS = "requestStatus"; + public final static String ARG_REQUEST_CREATION_TIME = "requestCreationTime"; + public final static String ARG_REQUEST_MODIFICATION_TIME = "requestModificationTime"; + public final static String ARG_REQUEST_NONCE = "nonce"; + public final static String ARG_OP = "op"; + public final static String ARG_REQUESTS = "requests"; + public final static String ARG_ERROR_CODE = "errorCode"; + public final static String ARG_ERROR_REASON = "errorReason"; + public final static String CERT_ATTR = "javax.servlet.request.X509Certificate"; + + // servlet config constants + public static final String PROFILE_ID = "profileId"; + public static final String AUTH_ID = "authId"; + public static final String ACL_METHOD = "aclMethod"; + public static final String AUTHZ_RESOURCE_NAME = "authzResourceName"; + public static final String AUTH_MGR = "authMgr"; + public static final String AUTHZ_MGR = "authzMgr"; + public static final String GET_CLIENT_CERT = "getClientCert"; + public static final String ACL_INFO = "ACLinfo"; + public static final String AUTHORITY_ID = "authorityId"; + public static final String PROFILE_SUB_ID = "profileSubId"; + + public final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5"; + public final static String LOGGING_SIGNED_AUDIT_AUTH_FAIL = + "LOGGING_SIGNED_AUDIT_AUTH_FAIL_4"; + public final static String LOGGING_SIGNED_AUDIT_AUTH_SUCCESS = + "LOGGING_SIGNED_AUDIT_AUTH_SUCCESS_3"; + public final static String LOGGING_SIGNED_AUDIT_AUTHZ_FAIL = + "LOGGING_SIGNED_AUDIT_AUTHZ_FAIL_4"; + public final static String LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS = + "LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS_4"; + public final static String LOGGING_SIGNED_AUDIT_ROLE_ASSUME = + "LOGGING_SIGNED_AUDIT_ROLE_ASSUME_3"; + public final static String SIGNED_AUDIT_CERT_REQUEST_REASON = + "requestNotes"; + + protected String profileID; + protected String profileSubId; + protected String aclMethod; + protected String authzResourceName; + protected String authMgr; + protected String getClientCert = "false"; + protected Locale locale; + + // subsystems + 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; + + //logging and stats + + protected ILogger logger = CMS.getLogger(); + protected IAuditor auditor = CMS.getAuditor(); + protected ILogger signedAuditLogger = CMS.getSignedAuditLogger(); + protected LinkedHashSet<String> statEvents = new LinkedHashSet<String>(); + + public Processor(String id, Locale locale) throws EPropertyNotFound, EBaseException { + IConfigStore cs = CMS.getConfigStore().getSubStore("processor." + id); + this.locale = locale; + this.profileID = cs.getString(PROFILE_ID, "").isEmpty() ? null : cs.getString(PROFILE_ID); + this.authzResourceName = cs.getString(AUTHZ_RESOURCE_NAME, "").isEmpty() ? null : + cs.getString(AUTHZ_RESOURCE_NAME); + this.authMgr = cs.getString(AUTH_MGR, "").isEmpty() ? null : cs.getString(AUTH_MGR); + this.getClientCert = cs.getString(GET_CLIENT_CERT, "").isEmpty() ? "false" : cs.getString(GET_CLIENT_CERT); + this.profileSubId = cs.getString(PROFILE_SUB_ID, "").isEmpty() ? IProfileSubsystem.ID : + cs.getString(PROFILE_SUB_ID); + + String aclInfo = cs.getString(ACL_INFO, "").isEmpty() ? null : cs.getString(ACL_INFO); + String authzMgr = cs.getString(AUTHZ_MGR, "").isEmpty() ? null : cs.getString(AUTHZ_MGR); + this.aclMethod = ServletUtils.getACLMethod(aclInfo, authzMgr, id); + + // currently unused but in servlet config + // authId = cs.getString(AUTH_ID, "").isEmpty() ? null : cs.getString(AUTH_ID); + + if (authority == null) { + throw new EBaseException("CertProcessor: authority is null"); + } + + queue = authority.getRequestQueue(); + if (queue == null) { + throw new EBaseException("CertProcessor: cannot get request queue"); + } + + if (profileSubId == null || profileSubId.equals("")) { + profileSubId = IProfileSubsystem.ID; + } + + ps = (IProfileSubsystem) CMS.getSubsystem(profileSubId); + if (ps == null) { + throw new EBaseException("CertProcessor: Profile Subsystem not found"); + } + + certdb = authority.getCertificateRepository(); + if (certdb == null) { + throw new EBaseException("CertProcessor: Certificate repository not found"); + } + } + + /****************************************** + * Stats - to be moved to Stats module + ******************************************/ + + public void startTiming(String event) { + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.startTiming(event, true); + } + statEvents.add(event); + } + + public void endTiming(String event) { + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.endTiming(event); + } + statEvents.remove(event); + } + + public void endAllEvents() { + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + Iterator<String> iter = statEvents.iterator(); + while (iter.hasNext()) { + String event = iter.next(); + statsSub.endTiming(event); + iter.remove(); + } + } + } + + /****************************************** + * Utility Functions + ******************************************/ + + public IRequest getRequest(String rid) throws EBaseException { + IRequest request = queue.findRequest(new RequestId(rid)); + return request; + } + + protected IRequest getOriginalRequest(BigInteger certSerial, ICertRecord rec) throws EBaseException { + MetaInfo metaInfo = (MetaInfo) rec.get(ICertRecord.ATTR_META_INFO); + if (metaInfo == null) { + CMS.debug("getOriginalRequest: cert record locating MetaInfo failed for serial number " + + certSerial.toString()); + return null; + } + + String rid = (String) metaInfo.get(ICertRecord.META_REQUEST_ID); + if (rid == null) { + CMS.debug("getOriginalRequest: cert record locating request id in MetaInfo failed " + + "for serial number " + certSerial.toString()); + return null; + } + + IRequest request = queue.findRequest(new RequestId(rid)); + return request; + } + + protected void printParameterValues(HashMap<String, String> data) { + CMS.debug("Start of CertProcessor Input Parameters"); + + for (Entry<String, String> entry : data.entrySet()) { + String paramName = entry.getKey(); + // added this facility so that password can be hidden, + // all sensitive parameters should be prefixed with + // __ (double underscores); however, in the event that + // a security parameter slips through, we perform multiple + // additional checks to insure that it is NOT displayed + if (paramName.startsWith("__") || + paramName.endsWith("password") || + paramName.endsWith("passwd") || + paramName.endsWith("pwd") || + paramName.equalsIgnoreCase("admin_password_again") || + paramName.equalsIgnoreCase("directoryManagerPwd") || + paramName.equalsIgnoreCase("bindpassword") || + paramName.equalsIgnoreCase("bindpwd") || + paramName.equalsIgnoreCase("passwd") || + paramName.equalsIgnoreCase("password") || + paramName.equalsIgnoreCase("pin") || + paramName.equalsIgnoreCase("pwd") || + paramName.equalsIgnoreCase("pwdagain") || + paramName.equalsIgnoreCase("uPasswd")) { + CMS.debug("CertProcessor Input Parameter " + paramName + "='(sensitive)'"); + } else { + CMS.debug("CertProcessor Input Parameter " + paramName + "='" + entry.getValue() + "'"); + } + } + + CMS.debug("End of CertProcessor Input Parameters"); + } + + /** + * get ssl client authenticated certificate + */ + public static X509Certificate getSSLClientCertificate(HttpServletRequest httpReq) + throws EBaseException { + X509Certificate cert = null; + + CMS.debug(CMS.getLogMessage("CMSGW_GETTING_SSL_CLIENT_CERT")); + + // iws60 support Java Servlet Spec V2.2, attribute + // javax.servlet.request.X509Certificate now contains array + // of X509Certificates instead of one X509Certificate object + X509Certificate[] allCerts = (X509Certificate[]) httpReq.getAttribute(CERT_ATTR); + + if (allCerts == null || allCerts.length == 0) { + throw new EBaseException("You did not provide a valid certificate for this operation"); + } + + cert = allCerts[0]; + + if (cert == null) { + // just don't have a cert. + + CMS.debug(CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL")); + return null; + } + + // convert to sun's x509 cert interface. + try { + byte[] certEncoded = cert.getEncoded(); + cert = new X509CertImpl(certEncoded); + } catch (CertificateEncodingException e) { + CMS.debug(CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL_ENCODE", e.getMessage())); + return null; + + } catch (CertificateException e) { + CMS.debug(CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL_DECODE", e.getMessage())); + return null; + } + return cert; + } + + public void log(int source, int level, String message) { + + if (logger == null) return; + + logger.log(ILogger.EV_SYSTEM, + null, + source, + level, + getClass().getSimpleName() + ": " + message); + } + + protected static Hashtable<String, String> toHashtable(HttpServletRequest req) { + Hashtable<String, String> httpReqHash = new Hashtable<String, String>(); + Enumeration<?> names = req.getParameterNames(); + + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + + httpReqHash.put(name, req.getParameter(name)); + } + return httpReqHash; + } + + /****************************************** + * AUTHENTICATION FUNCTIONS (move to Realm?) + ******************************************/ + + /* + * authenticate for renewal - more to add necessary params/values + * to the session context + */ + public IAuthToken authenticate(IProfileAuthenticator authenticator, + HttpServletRequest request, IRequest origReq, SessionContext context) throws EBaseException + { + IAuthToken authToken = authenticate(authenticator, request); + // For renewal, fill in necessary params + if (authToken != null) { + String ouid = origReq.getExtDataInString("auth_token.uid"); + // if the orig cert was manually approved, then there was + // no auth token uid. Try to get the uid from the cert dn + // itself, if possible + if (ouid == null) { + String sdn = (String) context.get("origSubjectDN"); + if (sdn != null) { + ouid = getUidFromDN(sdn); + if (ouid != null) + CMS.debug("CertProcessor: renewal: authToken original uid not found"); + } + } else { + CMS.debug("CertProcessor: renewal: authToken original uid found in orig request auth_token"); + } + String auid = authToken.getInString("uid"); + if (auid != null) { // not through ssl client auth + CMS.debug("CertProcessor: renewal: authToken uid found:" + auid); + // authenticated with uid + // put "orig_req.auth_token.uid" so that authz with + // UserOrigReqAccessEvaluator will work + if (ouid != null) { + context.put("orig_req.auth_token.uid", ouid); + CMS.debug("CertProcessor: renewal: authToken original uid found:" + ouid); + } else { + CMS.debug("CertProcessor: renewal: authToken original uid not found"); + } + } else { // through ssl client auth? + CMS.debug("CertProcessor: renewal: authToken uid not found:"); + // put in orig_req's uid + if (ouid != null) { + CMS.debug("CertProcessor: renewal: origReq uid not null:" + ouid + ". Setting authtoken"); + authToken.set("uid", ouid); + context.put(SessionContext.USER_ID, ouid); + } else { + CMS.debug("CertProcessor: renewal: origReq uid not found"); + // throw new EBaseException("origReq uid not found"); + } + } + + String userdn = origReq.getExtDataInString("auth_token.userdn"); + if (userdn != null) { + CMS.debug("CertProcessor: renewal: origReq userdn not null:" + userdn + ". Setting authtoken"); + authToken.set("userdn", userdn); + } else { + CMS.debug("CertProcessor: renewal: origReq userdn not found"); + // throw new EBaseException("origReq userdn not found"); + } + } else { + CMS.debug("CertProcessor: renewal: authToken null"); + } + return authToken; + } + + public IAuthToken authenticate(IProfileAuthenticator authenticator, + HttpServletRequest request) throws EBaseException { + AuthCredentials credentials = new AuthCredentials(); + + // build credential + Enumeration<String> authNames = authenticator.getValueNames(); + + if (authNames != null) { + while (authNames.hasMoreElements()) { + String authName = authNames.nextElement(); + + credentials.set(authName, request.getParameter(authName)); + } + } + + credentials.set("clientHost", request.getRemoteHost()); + IAuthToken authToken = authenticator.authenticate(credentials); + + SessionContext sc = SessionContext.getContext(); + if (sc != null) { + sc.put(SessionContext.AUTH_MANAGER_ID, authenticator.getName()); + String userid = authToken.getInString(IAuthToken.USER_ID); + if (userid != null) { + sc.put(SessionContext.USER_ID, userid); + } + } + + return authToken; + } + + public IAuthToken authenticate(HttpServletRequest request, IRequest origReq, IProfileAuthenticator authenticator, + SessionContext context, boolean isRenewal) throws EBaseException { + startTiming("profile_authentication"); + + IAuthToken authToken = null; + if (authenticator != null) { + CMS.debug("authenticate: authentication required."); + String uid_cred = "Unidentified"; + String uid_attempted_cred = "Unidentified"; + Enumeration<String> authIds = authenticator.getValueNames(); + //Attempt to possibly fetch attempted uid, may not always be available. + if (authIds != null) { + while (authIds.hasMoreElements()) { + String authName = authIds.nextElement(); + String value = request.getParameter(authName); + if (value != null) { + if (authName.equals("uid")) { + uid_attempted_cred = value; + } + } + } + } + + String authSubjectID = auditSubjectID(); + String authMgrID = authenticator.getName(); + String auditMessage = null; + try { + if (isRenewal) { + authToken = authenticate(authenticator, request, origReq, context); + } else { + authToken = authenticate(authenticator, request); + } + } catch (EBaseException e) { + CMS.debug("CertProcessor: authentication error " + e.toString()); + + authSubjectID += " : " + uid_cred; + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + authSubjectID, + ILogger.FAILURE, + authMgrID, + uid_attempted_cred); + audit(auditMessage); + + throw e; + } + + //Log successful authentication + //Attempt to get uid from authToken, most tokens respond to the "uid" cred. + uid_cred = authToken.getInString("uid"); + + if (uid_cred == null || uid_cred.length() == 0) { + uid_cred = "Unidentified"; + } + + authSubjectID = authSubjectID + " : " + uid_cred; + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_SUCCESS, + authSubjectID, + ILogger.SUCCESS, + authMgrID); + + audit(auditMessage); + } + endTiming("profile_authentication"); + return authToken; + } + + public IAuthToken authenticate(HttpServletRequest httpReq) + throws EBaseException { + return authenticate(httpReq, authMgr); + } + + public static void saveAuthToken(IAuthToken token, IRequest req) { + if (token != null && req != null) + req.setExtData(IRequest.AUTH_TOKEN, token); + + // # 56230 - expose auth token parameters to the policy predicate + if (token != null && req != null) { + Enumeration<String> e = token.getElements(); + while (e.hasMoreElements()) { + String n = e.nextElement(); + String[] x1 = token.getInStringArray(n); + if (x1 != null) { + for (int i = 0; i < x1.length; i++) { + CMS.debug("Setting " + IRequest.AUTH_TOKEN + "-" + n + + "(" + i + ")=" + x1[i]); + req.setExtData(IRequest.AUTH_TOKEN + "-" + n + "(" + i + ")", + x1[i]); + } + } else { + String x = token.getInString(n); + if (x != null) { + CMS.debug("Setting " + IRequest.AUTH_TOKEN + "-" + n + "=" + x); + req.setExtData(IRequest.AUTH_TOKEN + "-" + n, x); + } + } + } // while + } // if + } + + public IAuthToken authenticate(HttpServletRequest httpReq, String authMgrName) + throws EBaseException { + String auditMessage = null; + String auditSubjectID = ILogger.UNIDENTIFIED; + String auditAuthMgrID = ILogger.UNIDENTIFIED; + String auditUID = ILogger.UNIDENTIFIED; + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + IArgBlock httpArgs = CMS.createArgBlock(toHashtable(httpReq)); + SessionContext ctx = SessionContext.getContext(); + String ip = httpReq.getRemoteAddr(); + CMS.debug("IP: " + ip); + + if (ip != null) { + ctx.put(SessionContext.IPADDRESS, ip); + } + if (authMgrName != null) { + CMS.debug("AuthMgrName: " + authMgrName); + ctx.put(SessionContext.AUTH_MANAGER_ID, authMgrName); + } + // put locale into session context + ctx.put(SessionContext.LOCALE, locale); + + // + // check ssl client authentication if specified. + // + X509Certificate clientCert = null; + + if (getClientCert != null && getClientCert.equals("true")) { + CMS.debug("CMSServlet: retrieving SSL certificate"); + clientCert = getSSLClientCertificate(httpReq); + } + + // + // check authentication by auth manager if any. + // + if (authMgrName == null) { + + // Fixed Blackflag Bug #613900: Since this code block does + // NOT actually constitute an authentication failure, but + // rather the case in which a given servlet has been correctly + // configured to NOT require an authentication manager, the + // audit message called LOGGING_SIGNED_AUDIT_AUTH_FAIL has + // been removed. + + CMS.debug("CMSServlet: no authMgrName"); + return null; + } else { + // save the "Subject DN" of this certificate in case it + // must be audited as an authentication failure + if (clientCert == null) { + CMS.debug("CMSServlet: no client certificate found"); + } else { + String certUID = clientCert.getSubjectDN().getName(); + CMS.debug("CMSServlet: certUID=" + certUID); + + if (certUID != null) { + certUID = certUID.trim(); + + if (!(certUID.equals(""))) { + // reset the "auditUID" + auditUID = certUID; + } + } + } + + // reset the "auditAuthMgrID" + auditAuthMgrID = authMgrName; + } + AuthToken authToken = CMSGateway.checkAuthManager(httpReq, + httpArgs, + clientCert, + authMgrName); + if (authToken == null) { + return null; + } + String userid = authToken.getInString(IAuthToken.USER_ID); + + CMS.debug("CMSServlet: userid=" + userid); + + if (userid != null) { + ctx.put(SessionContext.USER_ID, userid); + } + + // reset the "auditSubjectID" + auditSubjectID = auditSubjectID(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditAuthMgrID); + + audit(auditMessage); + + return authToken; + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditAuthMgrID, + auditUID); + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } + } + + String getUidFromDN(String userdn) { + StringTokenizer st = new StringTokenizer(userdn, ","); + while (st.hasMoreTokens()) { + String t = st.nextToken(); + int i = t.indexOf("="); + + if (i == -1) { + continue; + } + String n = t.substring(0, i); + if (n.equalsIgnoreCase("uid")) { + String v = t.substring(i + 1); + CMS.debug("CertProcessor:: getUidFromDN(): uid found:" + v); + return v; + } else { + continue; + } + } + return null; + } + + /****************************************** + * AUTHZ FNCTIONS (to be moved to Realm?) + *****************************************/ + + public AuthzToken authorize(String authzMgrName, String resource, IAuthToken authToken, + String exp) throws EBaseException { + AuthzToken authzToken = null; + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditGroupID = auditGroupID(); + String auditACLResource = resource; + String auditOperation = "enroll"; + + try { + authzToken = authz.authorize(authzMgrName, authToken, exp); + if (authzToken != null) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditSubjectID, + ILogger.SUCCESS, + auditGroupID); + + audit(auditMessage); + } else { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditSubjectID, + ILogger.FAILURE, + auditGroupID); + + audit(auditMessage); + } + return authzToken; + } catch (EBaseException e) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditSubjectID, + ILogger.FAILURE, + auditGroupID); + + audit(auditMessage); + throw e; + } + } + + /** + * Authorize must occur after Authenticate + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_FAIL used when authorization has failed + * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS used when authorization is successful + * <li>signed.audit LOGGING_SIGNED_AUDIT_ROLE_ASSUME used when user assumes a role (in current CS that's when one + * accesses a role port) + * </ul> + * + * @param authzMgrName string representing the name of the authorization + * manager + * @param authToken the authentication token + * @param resource a string representing the ACL resource id as defined in + * the ACL resource list + * @param operation a string representing one of the operations as defined + * within the ACL statement (e. g. - "read" for an ACL statement containing + * "(read,write)") + * @exception EBaseException an error has occurred + * @return the authorization token + */ + public AuthzToken authorize(String authzMgrName, IAuthToken authToken, + String resource, String operation) { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditGroupID = auditGroupID(); + String auditID = auditSubjectID; + String auditACLResource = resource; + String auditOperation = operation; + + SessionContext auditContext = SessionContext.getExistingContext(); + String authManagerId = null; + + if (auditContext != null) { + authManagerId = (String) auditContext.get(SessionContext.AUTH_MANAGER_ID); + + if (authManagerId != null && authManagerId.equals("TokenAuth")) { + if (auditSubjectID.equals(ILogger.NONROLEUSER) || + auditSubjectID.equals(ILogger.UNIDENTIFIED)) { + CMS.debug("CMSServlet: in authorize... TokenAuth auditSubjectID unavailable, changing to auditGroupID"); + auditID = auditGroupID; + } + } + } + + // "normalize" the "auditACLResource" value + if (auditACLResource != null) { + auditACLResource = auditACLResource.trim(); + } + + // "normalize" the "auditOperation" value + if (auditOperation != null) { + auditOperation = auditOperation.trim(); + } + + if (authzMgrName == null) { + // Fixed Blackflag Bug #613900: Since this code block does + // NOT actually constitute an authorization failure, but + // rather the case in which a given servlet has been correctly + // configured to NOT require an authorization manager, the + // audit message called LOGGING_SIGNED_AUDIT_AUTHZ_FAIL and + // the audit message called LOGGING_SIGNED_AUDIT_ROLE_ASSUME + // (marked as a failure) have been removed. + + return null; + } + + try { + AuthzToken authzTok = authz.authorize(authzMgrName, + authToken, + resource, + operation); + + if (authzTok != null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditID, + ILogger.SUCCESS, + auditGroups(auditSubjectID)); + + audit(auditMessage); + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditID, + ILogger.FAILURE, + auditGroups(auditSubjectID)); + + audit(auditMessage); + } + + return authzTok; + } catch (Exception eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditID, + ILogger.FAILURE, + auditGroups(auditSubjectID)); + + audit(auditMessage); + + return null; + } + } + + public void authorize(String profileId, IProfile profile, IAuthToken authToken) throws EBaseException { + if (authToken != null) { + CMS.debug("CertProcessor authToken not null"); + + String acl = profile.getAuthzAcl(); + CMS.debug("CertProcessor: authz using acl: " + acl); + if (acl != null && acl.length() > 0) { + String resource = profileId + ".authz.acl"; + authorize(aclMethod, resource, authToken, acl); + } + } + } + + /****************************************** + * AUDIT FUNCTIONS (to be moved to Auditor?) + ******************************************/ + protected void audit(String msg) { + // in this case, do NOT strip preceding/trailing whitespace + // from passed-in String parameters + + if (signedAuditLogger == null) { + return; + } + + signedAuditLogger.log(ILogger.EV_SIGNED_AUDIT, + null, + ILogger.S_SIGNED_AUDIT, + ILogger.LL_SECURITY, + msg); + } + + /** + * Signed Audit Log Requester ID + * + * This method is called to obtain the "RequesterID" for + * a signed audit log message. + * <P> + * + * @param request the actual request + * @return id string containing the signed audit log message RequesterID + */ + protected String auditRequesterID(IRequest request) { + // if no signed audit object exists, bail + if (signedAuditLogger == null) { + return null; + } + + String requesterID = ILogger.UNIDENTIFIED; + + if (request != null) { + // overwrite "requesterID" if and only if "id" != null + String id = request.getRequestId().toString(); + + if (id != null) { + requesterID = id.trim(); + } + } + + return requesterID; + } + + /** + * Signed Audit Log Info Certificate Value + * + * This method is called to obtain the certificate from the passed in + * "X509CertImpl" for a signed audit log message. + * <P> + * + * @param request request containing an X509CertImpl + * @return cert string containing the certificate + */ + protected String auditInfoCertValue(IRequest request) { + // if no signed audit object exists, bail + if (signedAuditLogger == null) { + return null; + } + + X509CertImpl x509cert = request.getExtDataInCert( + IEnrollProfile.REQUEST_ISSUED_CERT); + + if (x509cert == null) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + byte rawData[] = null; + + try { + rawData = x509cert.getEncoded(); + } catch (CertificateEncodingException e) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + String cert = null; + + // convert "rawData" into "base64Data" + if (rawData != null) { + String base64Data = null; + + base64Data = Utils.base64encode(rawData).trim(); + + // extract all line separators from the "base64Data" + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < base64Data.length(); i++) { + if (!Character.isWhitespace(base64Data.charAt(i))) { + sb.append(base64Data.charAt(i)); + + } + } + cert = sb.toString(); + } + + if (cert != null) { + cert = cert.trim(); + + if (cert.equals("")) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } else { + return cert; + } + } else { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } + + protected String auditSubjectID() { + // if no signed audit object exists, bail + if (signedAuditLogger == null) { + return null; + } + + CMS.debug("CMSServlet: in auditSubjectID"); + String subjectID = null; + + // Initialize subjectID + SessionContext auditContext = SessionContext.getExistingContext(); + + CMS.debug("CMSServlet: auditSubjectID auditContext " + auditContext); + if (auditContext != null) { + subjectID = (String) + auditContext.get(SessionContext.USER_ID); + + CMS.debug("CMSServlet auditSubjectID: subjectID: " + subjectID); + if (subjectID != null) { + subjectID = subjectID.trim(); + } else { + subjectID = ILogger.NONROLEUSER; + } + } else { + subjectID = ILogger.UNIDENTIFIED; + } + + return subjectID; + } + + protected String auditGroupID() { + // if no signed audit object exists, bail + if (signedAuditLogger == null) { + return null; + } + + CMS.debug("CMSServlet: in auditGroupID"); + String groupID = null; + + // Initialize groupID + SessionContext auditContext = SessionContext.getExistingContext(); + + CMS.debug("CMSServlet: auditGroupID auditContext " + auditContext); + if (auditContext != null) { + groupID = (String) + auditContext.get(SessionContext.GROUP_ID); + + CMS.debug("CMSServlet auditGroupID: groupID: " + groupID); + if (groupID != null) { + groupID = groupID.trim(); + } else { + groupID = ILogger.NONROLEUSER; + } + } else { + groupID = ILogger.UNIDENTIFIED; + } + + return groupID; + } + + /** + * Signed Audit Log Info Value + * + * This method is called to obtain the "reason" for + * a signed audit log message. + * <P> + * + * @param request the actual request + * @return reason string containing the signed audit log message reason + */ + protected String auditInfoValue(IRequest request) { + // if no signed audit object exists, bail + if (signedAuditLogger == null) { + return null; + } + + String reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + + if (request != null) { + // overwrite "reason" if and only if "info" != null + String info = + request.getExtDataInString(SIGNED_AUDIT_CERT_REQUEST_REASON); + + if (info != null) { + reason = info.trim(); + + // overwrite "reason" if and only if "reason" is empty + if (reason.equals("")) { + reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } + } + + return reason; + } + + /** + * Signed Audit Log Info Certificate Value + * + * This method is called to obtain the certificate from the passed in + * "X509CertImpl" for a signed audit log message. + * <P> + * + * @param x509cert an X509CertImpl + * @return cert string containing the certificate + */ + protected String auditInfoCertValue(X509CertImpl x509cert) { + // if no signed audit object exists, bail + if (signedAuditLogger == null) { + return null; + } + + if (x509cert == null) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + byte rawData[] = null; + + try { + rawData = x509cert.getEncoded(); + } catch (CertificateEncodingException e) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + String cert = null; + + // convert "rawData" into "base64Data" + if (rawData != null) { + String base64Data = null; + + base64Data = Utils.base64encode(rawData).trim(); + + // extract all line separators from the "base64Data" + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < base64Data.length(); i++) { + if (!Character.isWhitespace(base64Data.charAt(i))) { + sb.append(base64Data.charAt(i)); + } + } + cert = sb.toString(); + } + + if (cert != null) { + cert = cert.trim(); + + if (cert.equals("")) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } else { + return cert; + } + } else { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } + + /** + * Signed Audit Groups + * + * This method is called to extract all "groups" associated + * with the "auditSubjectID()". + * <P> + * + * @param SubjectID string containing the signed audit log message SubjectID + * @return a delimited string of groups associated + * with the "auditSubjectID()" + */ + protected String auditGroups(String SubjectID) { + // if no signed audit object exists, bail + if (signedAuditLogger == null) { + return null; + } + + if ((SubjectID == null) || + (SubjectID.equals(ILogger.UNIDENTIFIED))) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + Enumeration<IGroup> groups = null; + + try { + groups = ug.findGroups("*"); + } catch (Exception e) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + StringBuffer membersString = new StringBuffer(); + + while (groups.hasMoreElements()) { + IGroup group = groups.nextElement(); + + if (group.isMember(SubjectID) == true) { + if (membersString.length() != 0) { + membersString.append(", "); + } + + membersString.append(group.getGroupID()); + } + } + + if (membersString.length() != 0) { + return membersString.toString(); + } else { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } + + public void validateNonce( + HttpServletRequest servletRequest, + String name, + Object id, + Long nonce) throws EBaseException { + + if (nonce == null) { + throw new BadRequestException("Missing nonce."); + } + + Map<Object, Long> nonces = authority.getNonces(servletRequest, name); + + Long storedNonce = nonces.get(id); + if (storedNonce == null) { + throw new BadRequestException("Nonce for "+name+" "+id+" does not exist."); + } + + if (!nonce.equals(storedNonce)) { + throw new ForbiddenException("Invalid nonce"); + } + + nonces.remove(id); + + CMS.debug("Processor: Nonce verified"); + } + + public String getUserMessage(String messageId, String... params) { + return CMS.getUserMessage(locale, messageId, params); + } + + public void audit(String message, String scope, String type, String id, Map<String, String> params, String status) { + + if (auditor == null) return; + + String auditMessage = CMS.getLogMessage( + message, + auditor.getSubjectID(), + status, + auditor.getParamString(scope, type, id, params)); + + auditor.log(auditMessage); + } + + /** + * Get the values of the fields annotated with @FormParam. + */ + public Map<String, String> getParams(Object object) { + + Map<String, String> map = new HashMap<String, String>(); + + // for each fields in the object + for (Method method : object.getClass().getMethods()) { + FormParam element = method.getAnnotation(FormParam.class); + if (element == null) continue; + + String name = element.value(); + + try { + // get the value from the object + Object value = method.invoke(object); + + // put the value in the map + map.put(name, value == null ? null : value.toString()); + + } catch (Exception e) { + // ignore inaccessible fields + e.printStackTrace(); + } + } + + return map; + } +} |