// --- 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.cert.scep; import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import netscape.ldap.*; import java.security.*; import java.security.MessageDigest; import netscape.security.x509.*; import netscape.security.pkcs.*; import netscape.security.util.*; import com.netscape.certsrv.base.*; import com.netscape.certsrv.authority.*; import com.netscape.certsrv.logging.*; import com.netscape.certsrv.request.*; import com.netscape.certsrv.request.IRequestQueue; import com.netscape.certsrv.ca.*; import com.netscape.certsrv.authentication.*; import com.netscape.certsrv.authentication.AuthCredentials; import com.netscape.certsrv.profile.*; import com.netscape.certsrv.ldap.*; import com.netscape.certsrv.publish.*; import com.netscape.certsrv.apps.*; import com.netscape.certsrv.common.*; import com.netscape.cms.servlet.profile.*; import org.mozilla.jss.pkcs7.*; import org.mozilla.jss.asn1.*; import org.mozilla.jss.*; import org.mozilla.jss.util.*; import org.mozilla.jss.crypto.*; import org.mozilla.jss.pkix.cert.Certificate; import com.netscape.cmsutil.scep.CRSPKIMessage; /** * This servlet deals with PKCS#10-based certificate requests from * CRS, now called SCEP, and defined at: * http://search.ietf.org/internet-drafts/draft-nourse-scep-02.txt * * The router is hardcoded to look for the http://host:80/cgi-bin/pkiclient.exe * * The HTTP parameters are 'operation' and 'message' * operation can be either 'GetCACert' or 'PKIOperation' * * @version $Revision$, $Date$ */ public class CRSEnrollment extends HttpServlet { protected IProfileSubsystem mProfileSubsystem = null; protected String mProfileId = null; protected ICertAuthority mAuthority; protected IConfigStore mConfig = null; protected IAuthSubsystem mAuthSubsystem; protected String mAppendDN=null; protected String mEntryObjectclass=null; protected boolean mCreateEntry=false; protected boolean mFlattenDN=false; private String mAuthManagerName; private String mSubstoreName; private boolean mEnabled = false; private boolean mUseCA = true; private String mNickname = null; private String mTokenName = ""; private String mHashAlgorithm = "SHA1"; private String mHashAlgorithmList = null; private String[] mAllowedHashAlgorithm; private String mConfiguredEncryptionAlgorithm = "DES3"; private String mEncryptionAlgorithm = "DES3"; private String mEncryptionAlgorithmList = null; private String[] mAllowedEncryptionAlgorithm; private Random mRandom = null; private int mNonceSizeLimit = 0; protected ILogger mLogger = CMS.getLogger(); private ICertificateAuthority ca; /* for hashing challenge password */ protected MessageDigest mSHADigest = null; private static final String PROP_SUBSTORENAME = "substorename"; private static final String PROP_AUTHORITY = "authority"; private static final String PROP_CRS = "crs"; private static final String PROP_CRSCA = "casubsystem"; private static final String PROP_CRSAUTHMGR = "authName"; private static final String PROP_APPENDDN = "appendDN"; private static final String PROP_CREATEENTRY= "createEntry"; private static final String PROP_FLATTENDN = "flattenDN"; private static final String PROP_ENTRYOC = "entryObjectclass"; // URL parameters private static final String URL_OPERATION = "operation"; private static final String URL_MESSAGE = "message"; // possible values for 'operation' private static final String OP_GETCACERT = "GetCACert"; private static final String OP_PKIOPERATION = "PKIOperation"; public static final String AUTH_PASSWORD = "pwd"; public static final String AUTH_CREDS = "AuthCreds"; public static final String AUTH_TOKEN = "AuthToken"; public static final String AUTH_FAILED = "AuthFailed"; public static final String SANE_DNSNAME = "DNSName"; public static final String SANE_IPADDRESS = "IPAddress"; public static final String CERTINFO = "CertInfo"; public static final String SUBJECTNAME = "SubjectName"; public static ObjectIdentifier OID_UNSTRUCTUREDNAME = null; public static ObjectIdentifier OID_UNSTRUCTUREDADDRESS = null; public static ObjectIdentifier OID_SERIALNUMBER = null; public CRSEnrollment(){} public static Hashtable toHashtable(HttpServletRequest req) { Hashtable httpReqHash = new Hashtable(); Enumeration names = req.getParameterNames(); while (names.hasMoreElements()) { String name = (String)names.nextElement(); httpReqHash.put(name, req.getParameter(name)); } return httpReqHash; } public void init(ServletConfig sc) { // Find the CertificateAuthority we should use for CRS. String crsCA = sc.getInitParameter(PROP_AUTHORITY); if (crsCA == null) crsCA = "ca"; mAuthority = (ICertAuthority) CMS.getSubsystem(crsCA); ca = (ICertificateAuthority)mAuthority; if (mAuthority == null) { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CANT_FIND_AUTHORITY",crsCA)); } try { if (mAuthority instanceof ISubsystem) { IConfigStore authorityConfig = ((ISubsystem)mAuthority).getConfigStore(); IConfigStore scepConfig = authorityConfig.getSubStore("scep"); mEnabled = scepConfig.getBoolean("enable", false); mHashAlgorithm = scepConfig.getString("hashAlgorithm", "SHA1"); mConfiguredEncryptionAlgorithm = scepConfig.getString("encryptionAlgorithm", "DES3"); mNonceSizeLimit = scepConfig.getInteger("nonceSizeLimit", 0); mHashAlgorithmList = scepConfig.getString("allowedHashAlgorithms", "SHA1,SHA256,SHA512"); mAllowedHashAlgorithm = mHashAlgorithmList.split(","); mEncryptionAlgorithmList = scepConfig.getString("allowedEncryptionAlgorithms", "DES3"); mAllowedEncryptionAlgorithm = mEncryptionAlgorithmList.split(","); mNickname = scepConfig.getString("nickname", ca.getNickname()); if (mNickname.equals(ca.getNickname())) { mTokenName = ca.getSigningUnit().getTokenName(); } else { mTokenName = scepConfig.getString("tokenname", ""); mUseCA = false; } } } catch (EBaseException e) { CMS.debug("CRSEnrollment: init: EBaseException: "+e); } mEncryptionAlgorithm = mConfiguredEncryptionAlgorithm; CMS.debug("CRSEnrollment: init: SCEP support is "+((mEnabled)?"enabled":"disabled")+"."); CMS.debug("CRSEnrollment: init: SCEP nickname: "+mNickname); CMS.debug("CRSEnrollment: init: CA nickname: "+ca.getNickname()); CMS.debug("CRSEnrollment: init: Token name: "+mTokenName); CMS.debug("CRSEnrollment: init: Is SCEP using CA keys: "+mUseCA); CMS.debug("CRSEnrollment: init: mNonceSizeLimit: "+mNonceSizeLimit); CMS.debug("CRSEnrollment: init: mHashAlgorithm: "+mHashAlgorithm); CMS.debug("CRSEnrollment: init: mHashAlgorithmList: "+mHashAlgorithmList); for (int i = 0; i < mAllowedHashAlgorithm.length; i++) { mAllowedHashAlgorithm[i] = mAllowedHashAlgorithm[i].trim(); CMS.debug("CRSEnrollment: init: mAllowedHashAlgorithm["+i+"]="+mAllowedHashAlgorithm[i]); } CMS.debug("CRSEnrollment: init: mEncryptionAlgorithm: "+mEncryptionAlgorithm); CMS.debug("CRSEnrollment: init: mEncryptionAlgorithmList: "+mEncryptionAlgorithmList); for (int i = 0; i < mAllowedEncryptionAlgorithm.length; i++) { mAllowedEncryptionAlgorithm[i] = mAllowedEncryptionAlgorithm[i].trim(); CMS.debug("CRSEnrollment: init: mAllowedEncryptionAlgorithm["+i+"]="+mAllowedEncryptionAlgorithm[i]); } try { mProfileSubsystem = (IProfileSubsystem)CMS.getSubsystem("profile"); mProfileId = sc.getInitParameter("profileId"); CMS.debug("CRSEnrollment: init: mProfileId="+mProfileId); mAuthSubsystem = (IAuthSubsystem)CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); mAuthManagerName = sc.getInitParameter(PROP_CRSAUTHMGR); mAppendDN = sc.getInitParameter(PROP_APPENDDN); String tmp = sc.getInitParameter(PROP_CREATEENTRY); if (tmp != null && tmp.trim().equalsIgnoreCase("true")) mCreateEntry = true; else mCreateEntry = false; tmp = sc.getInitParameter(PROP_FLATTENDN); if (tmp != null && tmp.trim().equalsIgnoreCase("true")) mFlattenDN = true; else mFlattenDN = false; mEntryObjectclass = sc.getInitParameter(PROP_ENTRYOC); if (mEntryObjectclass == null) mEntryObjectclass = "cep"; mSubstoreName = sc.getInitParameter(PROP_SUBSTORENAME); if (mSubstoreName == null) mSubstoreName = "default"; } catch (Exception e) { } OID_UNSTRUCTUREDNAME = X500NameAttrMap.getDefault().getOid("UNSTRUCTUREDNAME"); OID_UNSTRUCTUREDADDRESS = X500NameAttrMap.getDefault().getOid("UNSTRUCTUREDADDRESS"); OID_SERIALNUMBER = X500NameAttrMap.getDefault().getOid("SERIALNUMBER"); try { mSHADigest = MessageDigest.getInstance("SHA1"); } catch (NoSuchAlgorithmException e) { } mRandom = new Random(); } /** * * Service a CRS Request. It all starts here. This is where the message from the * router is processed * * @param httpReq The HttpServletRequest. * @param httpResp The HttpServletResponse. * */ public void service(HttpServletRequest httpReq, HttpServletResponse httpResp) throws ServletException { boolean running_state = CMS.isInRunningState(); if (!running_state) throw new ServletException( "CMS server is not ready to serve."); String operation = null; String message = null; mEncryptionAlgorithm = mConfiguredEncryptionAlgorithm; // Parse the URL from the HTTP Request. Split it up into // a structure which enables us to read the form elements IArgBlock input = CMS.createArgBlock(toHashtable(httpReq)); try { // Read in two form parameters - the router sets these operation = (String)input.get(URL_OPERATION); CMS.debug("operation=" + operation); message = (String)input.get(URL_MESSAGE); CMS.debug("message=" + message); if (!mEnabled) { CMS.debug("CRSEnrollment: SCEP support is disabled."); throw new ServletException("SCEP support is disabled."); } if (operation == null) { // 'operation' is mandatory. throw new ServletException("Bad request: operation missing from URL"); } /** * the router can make two kinds of requests * 1) simple request for CA cert * 2) encoded, signed, enveloped request for anything else (PKIOperation) */ if (operation.equals(OP_GETCACERT)) { handleGetCACert(httpReq, httpResp); } else if (operation.equals(OP_PKIOPERATION)) { String decodeMode = (String)input.get("decode"); if (decodeMode == null || decodeMode.equals("false")) { handlePKIOperation(httpReq, httpResp, message); } else { decodePKIMessage(httpReq, httpResp, message); } } else { CMS.debug("Invalid operation " + operation); throw new ServletException("unknown operation requested: "+operation); } } catch (ServletException e) { CMS.debug("ServletException " + e); throw new ServletException(e.getMessage().toString()); } catch (Exception e) { CMS.debug("Service exception " + e); log(ILogger.LL_FAILURE,e.getMessage()); } } /** * Log a message to the system log */ private void log(int level, String msg) { mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, level, "CEP Enrollment: "+msg); } private boolean isAlgorithmAllowed (String[] allowedAlgorithm, String algorithm) { boolean allowed = false; if (algorithm != null && algorithm.length() > 0) { for (int i = 0; i < allowedAlgorithm.length; i++) { if (algorithm.equalsIgnoreCase(allowedAlgorithm[i])) { allowed = true; } } } return allowed; } public IAuthToken authenticate(AuthCredentials credentials, IProfileAuthenticator authenticator, HttpServletRequest request) throws EBaseException { // build credential Enumeration authNames = authenticator.getValueNames(); if (authNames != null) { while (authNames.hasMoreElements()) { String authName = (String) authNames.nextElement(); credentials.set(authName, request.getParameter(authName)); } } credentials.set("clientHost", request.getRemoteHost()); IAuthToken authToken = authenticator.authenticate(credentials); if (authToken == null) { return null; } 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; } /** * Return the CA certificate back to the requestor. * This needs to be changed so that if the CA has a certificate chain, * the whole thing should get packaged as a PKIMessage (degnerate PKCS7 - no * signerInfo) */ public void handleGetCACert(HttpServletRequest httpReq, HttpServletResponse httpResp) throws ServletException { java.security.cert.X509Certificate[] chain = null; CertificateChain certChain = mAuthority.getCACertChain(); try { if (certChain == null) { throw new ServletException("Internal Error: cannot get CA Cert"); } chain = certChain.getChain(); byte[] bytes = null; int i = 0; String message = (String)httpReq.getParameter(URL_MESSAGE); CMS.debug("handleGetCACert message=" + message); if (message != null) { try { int j = Integer.parseInt(message); if (j < chain.length) { i = j; } } catch (NumberFormatException e1) { } } CMS.debug("handleGetCACert selected chain=" + i); if (mUseCA) { bytes = chain[i].getEncoded(); } else { CryptoContext cx = new CryptoContext(); bytes = cx.getSigningCert().getEncoded(); } httpResp.setContentType("application/x-x509-ca-cert"); // The following code may be used one day to encode // the RA/CA cert chain for RA mode, but it will need some // work. /****** SET certs = new SET(); for (int i=0; i" + transactionID + ""; // End-User or RA's IP address responseData = responseData + "" + httpReq.getRemoteAddr() + ""; responseData = responseData + "" + httpReq.getRemoteHost() + ""; // Deal with Nonces byte[] sn = req.getSenderNonce(); // Deal with message type String mt = req.getMessageType(); responseData = responseData + "" + mt + ""; PKCS10 p10 = (PKCS10)req.getP10(); X500Name p10subject = p10.getSubjectName(); responseData = responseData + "" + p10subject.toString() + ""; String pkcs10Attr = ""; PKCS10Attributes p10atts = p10.getAttributes(); Enumeration e = p10atts.getElements(); while (e.hasMoreElements()) { PKCS10Attribute p10a = (PKCS10Attribute)e.nextElement(); CertAttrSet attr = p10a.getAttributeValue(); if (attr.getName().equals(ChallengePassword.NAME)) { if (attr.get(ChallengePassword.PASSWORD) != null) { pkcs10Attr = pkcs10Attr + "" + (String)attr.get(ChallengePassword.PASSWORD) + ""; } } String extensionsStr = ""; if (attr.getName().equals(ExtensionsRequested.NAME)) { Enumeration exts = ((ExtensionsRequested)attr).getExtensions().elements(); while (exts.hasMoreElements()) { Extension ext = (Extension) exts.nextElement(); if (ext.getExtensionId().equals( OIDMap.getOID(SubjectAlternativeNameExtension.IDENT)) ) { DerOutputStream dos = new DerOutputStream(); SubjectAlternativeNameExtension sane = new SubjectAlternativeNameExtension( Boolean.valueOf(false), // noncritical ext.getExtensionValue()); Vector v = (Vector) sane.get(SubjectAlternativeNameExtension. SUBJECT_NAME); Enumeration gne = v.elements(); StringBuffer subjAltNameStr = new StringBuffer(); while (gne.hasMoreElements()) { GeneralNameInterface gni = (GeneralNameInterface) gne.nextElement(); if (gni instanceof GeneralName) { GeneralName genName = (GeneralName) gni; String gn = genName.toString(); int colon = gn.indexOf(':'); String gnType = gn.substring(0,colon).trim(); String gnValue = gn.substring(colon+1).trim(); subjAltNameStr.append("<"); subjAltNameStr.append(gnType); subjAltNameStr.append(">"); subjAltNameStr.append(gnValue); subjAltNameStr.append(""); } } // while extensionsStr = "" + subjAltNameStr.toString() + ""; } // if } // while pkcs10Attr = pkcs10Attr + "" + extensionsStr + ""; } // if extensions } // while responseData = responseData + "" + pkcs10Attr + ""; } catch (ServletException e) { throw new ServletException(e.getMessage().toString()); } catch (CRSInvalidSignatureException e) { CMS.debug("handlePKIMessage exception " + e); CMS.debug(e); } catch (Exception e) { CMS.debug("handlePKIMessage exception " + e); CMS.debug(e); throw new ServletException("Failed to process message in CEP servlet: "+ e.getMessage()); } // We have now processed the request, and need to make the response message try { responseData = "" + responseData + ""; // Get the response coding response = responseData.getBytes(); // Encode the httpResp into B64 httpResp.setContentType("application/xml"); httpResp.setContentLength(response.length); httpResp.getOutputStream().write(response); httpResp.getOutputStream().flush(); int i1 = responseData.indexOf(""); if (i1 > -1) { i1 += 10; // 10 is a length of "" int i2 = responseData.indexOf("", i1); if (i2 > -1) { responseData = responseData.substring(0, i1) + "********" + responseData.substring(i2, responseData.length()); } } CMS.debug("Output (decoding) PKIOperation response:"); CMS.debug(responseData); } catch (Exception e) { throw new ServletException("Failed to create response for CEP message"+e.getMessage()); } } /** * finds a request with this transaction ID. * If could not find any request - return null * If could only find 'rejected' or 'cancelled' requests, return null * If found 'pending' or 'completed' request - return that request */ public void handlePKIOperation(HttpServletRequest httpReq, HttpServletResponse httpResp, String msg) throws ServletException { CryptoContext cx=null; CRSPKIMessage req=null; CRSPKIMessage crsResp=null; byte[] decodedPKIMessage; byte[] response=null; X509CertImpl cert = null; decodedPKIMessage = com.netscape.osutil.OSUtil.AtoB(msg); try { ByteArrayInputStream is = new ByteArrayInputStream(decodedPKIMessage); // We make two CRSPKIMessages. One of them, is the request, so we initialize // it from the DER given to us from the router. // The second is the response, and we'll fill this in as we go. if (decodedPKIMessage.length < 50) { throw new ServletException("CRS request is too small to be a real request ("+ decodedPKIMessage.length+" bytes)"); } try { req = new CRSPKIMessage(is); String ea = req.getEncryptionAlgorithm(); if (!isAlgorithmAllowed (mAllowedEncryptionAlgorithm, ea)) { CMS.debug("CRSEnrollment: handlePKIOperation: Encryption algorithm '"+ea+ "' is not allowed ("+mEncryptionAlgorithmList+")."); throw new ServletException("Encryption algorithm '"+ea+ "' is not allowed ("+mEncryptionAlgorithmList+")."); } String da = req.getDigestAlgorithmName(); if (!isAlgorithmAllowed (mAllowedHashAlgorithm, da)) { CMS.debug("CRSEnrollment: handlePKIOperation: Hashing algorithm '"+da+ "' is not allowed ("+mHashAlgorithmList+")."); throw new ServletException("Hashing algorithm '"+da+ "' is not allowed ("+mHashAlgorithmList+")."); } if (ea != null) { mEncryptionAlgorithm = ea; } crsResp = new CRSPKIMessage(); } catch (ServletException e) { throw new ServletException(e.getMessage().toString()); } catch (Exception e) { CMS.debug(e); throw new ServletException("Could not decode the request."); } crsResp.setMessageType(crsResp.mType_CertRep); // Create a new crypto context for doing all the crypto operations cx = new CryptoContext(); // Verify Signature on message (throws exception if sig bad) verifyRequest(req,cx); // Deal with Transaction ID String transactionID = req.getTransactionID(); if (transactionID == null) { throw new ServletException("Error: malformed PKIMessage - missing transactionID"); } else { crsResp.setTransactionID(transactionID); } // Deal with Nonces byte[] sn = req.getSenderNonce(); if (sn == null) { throw new ServletException("Error: malformed PKIMessage - missing sendernonce"); } else { if (mNonceSizeLimit > 0 && sn.length > mNonceSizeLimit) { byte[] snLimited = (mNonceSizeLimit > 0)? new byte[mNonceSizeLimit]: null; System.arraycopy(sn, 0, snLimited, 0, mNonceSizeLimit); crsResp.setRecipientNonce(snLimited); } else { crsResp.setRecipientNonce(sn); } byte[] serverNonce = new byte[16]; mRandom.nextBytes(serverNonce); crsResp.setSenderNonce(serverNonce); // crsResp.setSenderNonce(new byte[] {0}); } // Deal with message type String mt = req.getMessageType(); if (mt == null) { throw new ServletException("Error: malformed PKIMessage - missing messageType"); } // now run appropriate code, depending on message type if (mt.equals(req.mType_PKCSReq)) { CMS.debug("Processing PKCSReq"); try { // Check if there is an existing request. If this returns non-null, // then the request is 'active' (either pending or completed) in // which case, we compare the hash of the new request to the hash of the // one in the queue - if they are the same, I return the state of the // original request - as if it was 'getCertInitial' message. // If the hashes are different, then the user attempted to enroll // for a new request with the same txid, which is not allowed - // so we return 'failure'. IRequest cmsRequest= findRequestByTransactionID(req.getTransactionID(),true); // If there was no request (with a cert) with this transaction ID, // process it as a new request cert = handlePKCSReq(httpReq, cmsRequest,req,crsResp,cx); } catch (CRSFailureException e) { throw new ServletException("Couldn't handle CEP request (PKCSReq) - "+e.getMessage()); } } else if (mt.equals(req.mType_GetCertInitial)) { CMS.debug("Processing GetCertInitial"); cert = handleGetCertInitial(req,crsResp); } else { CMS.debug("Invalid request type " + mt); } } catch (ServletException e) { throw new ServletException(e.getMessage().toString()); } catch (CRSInvalidSignatureException e) { CMS.debug("handlePKIMessage exception " + e); CMS.debug(e); crsResp.setFailInfo(crsResp.mFailInfo_badMessageCheck); } catch (Exception e) { CMS.debug("handlePKIMessage exception " + e); CMS.debug(e); throw new ServletException("Failed to process message in CEP servlet: "+ e.getMessage()); } // We have now processed the request, and need to make the response message try { // make the response processCertRep(cx, cert,crsResp, req); // Get the response coding response = crsResp.getResponse(); // Encode the crsResp into B64 httpResp.setContentType("application/x-pki-message"); httpResp.setContentLength(response.length); httpResp.getOutputStream().write(response); httpResp.getOutputStream().flush(); CMS.debug("Output PKIOperation response:"); CMS.debug(CMS.BtoA(response)); } catch (Exception e) { throw new ServletException("Failed to create response for CEP message"+e.getMessage()); } } /** * finds a request with this transaction ID. * If could not find any request - return null * If could only find 'rejected' or 'cancelled' requests, return null * If found 'pending' or 'completed' request - return that request */ public IRequest findRequestByTransactionID(String txid, boolean ignoreRejected) throws EBaseException { /* Check if certificate request has been completed */ IRequestQueue rq = ca.getRequestQueue(); IRequest foundRequest = null; Enumeration rids = rq.findRequestsBySourceId(txid); if (rids == null) { return null; } int count=0; while (rids.hasMoreElements()) { RequestId rid = (RequestId) rids.nextElement(); if (rid == null) { continue; } IRequest request = rq.findRequest(rid); if (request == null) { continue; } if ( !ignoreRejected || request.getRequestStatus().equals(RequestStatus.PENDING) || request.getRequestStatus().equals(RequestStatus.COMPLETE)) { if (foundRequest != null) { } foundRequest = request; } } return foundRequest; } /** * Called if the router is requesting us to send it its certificate * Examine request queue for a request matching the transaction ID. * Ignore any rejected or cancelled requests. * * If a request is found in the pending state, the response should be * 'pending' * * If a request is found in the completed state, the response should be * to return the certificate * * If no request is found, the response should be to return null * */ public X509CertImpl handleGetCertInitial(CRSPKIMessage req,CRSPKIMessage resp) { IRequest foundRequest=null; // already done by handlePKIOperation // resp.setRecipientNonce(req.getSenderNonce()); // resp.setSenderNonce(null); try { foundRequest = findRequestByTransactionID(req.getTransactionID(),false); } catch (EBaseException e) { } if (foundRequest == null) { resp.setFailInfo(resp.mFailInfo_badCertId); resp.setPKIStatus(resp.mStatus_FAILURE); return null; } return makeResponseFromRequest(req,resp,foundRequest); } public void verifyRequest(CRSPKIMessage req, CryptoContext cx) throws CRSInvalidSignatureException { // Get Signed Data byte[] reqAAbytes = req.getAA(); byte[] reqAAsig = req.getAADigest(); } /** * Create an entry for this user in the publishing directory * */ private boolean createEntry(String dn) { boolean result = false; IPublisherProcessor ldapPub = mAuthority.getPublisherProcessor(); if (ldapPub == null || !ldapPub.enabled()) { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_CREATE_ENTRY_FROM_CEP")); return result; } ILdapConnFactory connFactory = ((IPublisherProcessor)ldapPub).getLdapConnModule().getLdapConnFactory(); if (connFactory == null) { return result; } LDAPConnection connection=null; try { connection = connFactory.getConn(); String[] objectclasses = { "top", mEntryObjectclass }; LDAPAttribute ocAttrs = new LDAPAttribute("objectclass",objectclasses); LDAPAttributeSet attrSet = new LDAPAttributeSet(); attrSet.add(ocAttrs); LDAPEntry newEntry = new LDAPEntry(dn, attrSet); connection.add(newEntry); result=true; } catch (Exception e) { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_FAIL_CREAT_ENTRY_EXISTS",dn)); } finally { try { connFactory.returnConn(connection); } catch (Exception f) {} } return result; } /** * Here we decrypt the PKCS10 message from the client * */ public void unwrapPKCS10(CRSPKIMessage req, CryptoContext cx) throws ServletException, CryptoManager.NotInitializedException, CryptoContext.CryptoContextException, CRSFailureException { byte[] decryptedP10bytes = null; SymmetricKey sk; SymmetricKey skinternal; SymmetricKey.Type skt; KeyWrapper kw; Cipher cip; EncryptionAlgorithm ea; boolean errorInRequest = false; // Unwrap the session key with the Cert server key try { kw = cx.getKeyWrapper(); kw.initUnwrap(cx.getPrivateKey(),null); skt = SymmetricKey.Type.DES; ea = EncryptionAlgorithm.DES_CBC; if (mEncryptionAlgorithm != null && mEncryptionAlgorithm.equals("DES3")) { skt = SymmetricKey.Type.DES3; ea = EncryptionAlgorithm.DES3_CBC; } sk = kw.unwrapSymmetric(req.getWrappedKey(), skt, SymmetricKey.Usage.DECRYPT, 0); // keylength is ignored skinternal = cx.getDESKeyGenerator().clone(sk); cip = skinternal.getOwningToken().getCipherContext(ea); cip.initDecrypt(skinternal,(new IVParameterSpec(req.getIV()))); decryptedP10bytes = cip.doFinal(req.getEncryptedPkcs10()); CMS.debug("decryptedP10bytes:"); CMS.debug(decryptedP10bytes); req.setP10(new PKCS10(decryptedP10bytes)); } catch (Exception e) { CMS.debug("failed to unwrap PKCS10 " + e); throw new CRSFailureException("Could not unwrap PKCS10 blob: "+e.getMessage()); } } private void getDetailFromRequest(CRSPKIMessage req, CRSPKIMessage crsResp) throws CRSFailureException { IRequest issueReq = null; X509CertImpl issuedCert=null; Vector extensionsRequested = null; SubjectAlternativeNameExtension sane = null; CertAttrSet requested_ext = null; try { PKCS10 p10 = (PKCS10)req.getP10(); if (p10 == null) { crsResp.setFailInfo(crsResp.mFailInfo_badMessageCheck); crsResp.setPKIStatus(crsResp.mStatus_FAILURE); throw new CRSFailureException("Failed to decode pkcs10 from CEP request"); } AuthCredentials authCreds = new AuthCredentials(); String challengePassword = null; // Here, we make a new CertInfo - it's a new start for a certificate X509CertInfo certInfo = CMS.getDefaultX509CertInfo(); // get some stuff out of the request X509Key key = p10.getSubjectPublicKeyInfo(); X500Name p10subject = p10.getSubjectName(); X500Name subject=null; // The following code will copy all the attributes // into the AuthCredentials so they can be used for // authentication // // Optionally, you can re-map the subject name from: // one RDN, with many AVA's to // many RDN's with one AVA in each. Enumeration rdne = p10subject.getRDNs(); Vector rdnv = new Vector(); Hashtable sanehash = new Hashtable(); X500NameAttrMap xnap = X500NameAttrMap.getDefault(); while (rdne.hasMoreElements()) { RDN rdn = (RDN) rdne.nextElement(); int i=0; AVA[] oldavas = rdn.getAssertion(); for (i=0; i 0) { Hashtable encodedPrints = new Hashtable(fingerprints.size()); Enumeration e = fingerprints.keys(); while (e.hasMoreElements()) { String key = (String)e.nextElement(); byte[] value = (byte[])fingerprints.get(key); encodedPrints.put(key, CMS.BtoA(value)); } pkiReq.setExtData(IRequest.FINGERPRINTS, encodedPrints); } pkiReq.setSourceId(req.getTransactionID()); rq.processRequest(pkiReq); crsResp.setPKIStatus(crsResp.mStatus_SUCCESS); mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, AuditFormat.LEVEL, AuditFormat.ENROLLMENTFORMAT, new Object[] { pkiReq.getRequestId(), AuditFormat.FROMROUTER, mAuthManagerName == null ? AuditFormat.NOAUTH : mAuthManagerName, "pending", subject , ""} ); return pkiReq; } public Hashtable makeFingerPrints(CRSPKIMessage req) { Hashtable fingerprints = new Hashtable(); MessageDigest md; String[] hashes = new String[] {"MD2", "MD5", "SHA1", "SHA256", "SHA512"}; PKCS10 p10 = (PKCS10)req.getP10(); for (int i=0;i