diff options
Diffstat (limited to 'base/common/src/com/netscape/cms/servlet/request')
18 files changed, 6091 insertions, 0 deletions
diff --git a/base/common/src/com/netscape/cms/servlet/request/CertReqParser.java b/base/common/src/com/netscape/cms/servlet/request/CertReqParser.java new file mode 100644 index 000000000..d8fc68a69 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/CertReqParser.java @@ -0,0 +1,925 @@ +// --- 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.request; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.lang.reflect.Array; +import java.math.BigInteger; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; + +import netscape.security.extensions.NSCertTypeExtension; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.BasicConstraintsExtension; +import netscape.security.x509.CRLExtensions; +import netscape.security.x509.CRLReasonExtension; +import netscape.security.x509.CertificateAlgorithmId; +import netscape.security.x509.CertificateChain; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.Extension; +import netscape.security.x509.RevocationReason; +import netscape.security.x509.RevokedCertImpl; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +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.base.IPrettyPrintFormat; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.RawJS; + +/** + * Output a 'pretty print' of a certificate request + * + * @version $Revision$, $Date$ + */ +public class CertReqParser extends ReqParser { + + public static final CertReqParser DETAIL_PARSER = new CertReqParser(true); + public static final CertReqParser NODETAIL_PARSER = new CertReqParser(false); + + private boolean mDetails = true; + private IPrettyPrintFormat pp = null; + + /** + * Constructs a certificate request parser. + */ + public CertReqParser() { + pp = CMS.getPrettyPrintFormat(":"); + } + + /** + * Constructs a certificate request parser. + * + * @param details return detailed information (this can be time consuming) + */ + public CertReqParser(boolean details) { + mDetails = details; + pp = CMS.getPrettyPrintFormat(":"); + } + + private static final String EXT_PRETTYPRINT = "ext_prettyprint"; + + private static final String DOT = "."; + private static final String LB = "["; + private static final String RB = "]"; + private static final String EQ = " = "; + + private static final String HTTP_PARAMS_COUNTER = IRequest.HTTP_PARAMS + LB + "httpParamsCount++" + RB; + private static final String HTTP_HEADERS_COUNTER = IRequest.HTTP_HEADERS + LB + "httpHeadersCount++" + RB; + private static final String AUTH_TOKEN_COUNTER = IRequest.AUTH_TOKEN + LB + "authTokenCount++" + RB; + private static final String SERVER_ATTRS_COUNTER = IRequest.SERVER_ATTRS + LB + "serverAttrsCount++" + RB; + + /** + * Fills in certificate specific request attributes. + */ + public void fillRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg) + throws EBaseException { + if (req.getExtDataInCertInfoArray(IRequest.CERT_INFO) != null) { + fillX509RequestIntoArg(l, req, argSet, arg); + } else if (req.getExtDataInRevokedCertArray(IRequest.CERT_INFO) != null) { + fillRevokeRequestIntoArg(l, req, argSet, arg); + } else { + //o = req.get(IRequest.OLD_CERTS); + //if (o != null) + fillRevokeRequestIntoArg(l, req, argSet, arg); + } + } + + private void fillX509RequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg) + throws EBaseException { + + // fill in the standard attributes + super.fillRequestIntoArg(l, req, argSet, arg); + + arg.addStringValue("certExtsEnabled", "yes"); + + int saCounter = 0; + Enumeration<String> enum1 = req.getExtDataKeys(); + + // gross hack + String prefix = "record."; + + if (argSet.getHeader() == arg) + prefix = "header."; + + while (enum1.hasMoreElements()) { + String name = enum1.nextElement(); + + if (mDetails) { + // show all http parameters stored in request. + if (name.equalsIgnoreCase(IRequest.HTTP_PARAMS)) { + Hashtable<String, String> http_params = req.getExtDataInHashtable(name); + // show certType specially + String certType = http_params.get(IRequest.CERT_TYPE); + + if (certType != null) { + arg.addStringValue(IRequest.CERT_TYPE, certType); + } + String presenceServerExt = (String) http_params.get("PresenceServerExtension"); + + if (presenceServerExt != null) { + arg.addStringValue("PresenceServerExtension", presenceServerExt); + } + // show all http parameters in request + int counter = 0; + Enumeration<String> elms = http_params.keys(); + + while (elms.hasMoreElements()) { + String parami = + IRequest.HTTP_PARAMS + LB + String.valueOf(counter++) + RB; + // hack + String n = elms.nextElement(); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(n) + "\";\n\r" + + prefix + parami + ".value=\"" + + CMSTemplate.escapeJavaScriptStringHTML( + http_params.get(n).toString()) + "\""; + + arg.set(parami, new RawJS(rawJS)); + } + } // show all http headers stored in request. + else if (name.equalsIgnoreCase(IRequest.HTTP_HEADERS)) { + Hashtable<String, String> http_hdrs = req.getExtDataInHashtable(name); + Enumeration<String> elms = http_hdrs.keys(); + int counter = 0; + + while (elms.hasMoreElements()) { + String parami = + IRequest.HTTP_HEADERS + LB + String.valueOf(counter++) + RB; + // hack + String n = elms.nextElement(); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(n) + "\";\n\r" + + prefix + parami + ".value=\"" + + CMSTemplate.escapeJavaScriptStringHTML( + http_hdrs.get(n).toString()) + "\""; + + arg.set(parami, new RawJS(rawJS)); + } + } // show all auth token stored in request. + else if (name.equalsIgnoreCase(IRequest.AUTH_TOKEN)) { + IAuthToken auth_token = req.getExtDataInAuthToken(name); + Enumeration<String> elms = auth_token.getElements(); + int counter = 0; + + while (elms.hasMoreElements()) { + String parami = + IRequest.AUTH_TOKEN + LB + String.valueOf(counter++) + RB; + // hack + String n = elms.nextElement(); + Object authTokenValue = auth_token.getInStringArray(n); + if (authTokenValue == null) { + authTokenValue = auth_token.getInString(n); + } + String v = expandValue(prefix + parami + ".value", + authTokenValue); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(n) + "\";\n" + v; + + arg.set(parami, new RawJS(rawJS)); + } + } // all others are request attrs from policy or internal modules. + else { + Object val; + if (req.isSimpleExtDataValue(name)) { + val = req.getExtDataInString(name); + } else { + val = req.getExtDataInStringArray(name); + if (val == null) { + val = req.getExtDataInHashtable(name); + } + } + String valstr = ""; + // hack + String parami = + IRequest.SERVER_ATTRS + LB + String.valueOf(saCounter++) + RB; + + if (name.equalsIgnoreCase(IRequest.ISSUED_CERTS) && mDetails && + (req.getRequestStatus().toString().equals(RequestStatus.COMPLETE_STRING) || + req.getRequestType().equals(IRequest.GETREVOCATIONINFO_REQUEST))) { + X509CertImpl issuedCert[] = + req.getExtDataInCertArray(IRequest.ISSUED_CERTS); + if (issuedCert != null && issuedCert[0] != null) { + val = "<pre>" + CMS.getCertPrettyPrint(issuedCert[0]).toString(l) + "</pre>"; + } + } else if (name.equalsIgnoreCase(IRequest.CERT_INFO) && mDetails) { + X509CertInfo[] certInfo = + req.getExtDataInCertInfoArray(IRequest.CERT_INFO); + if (certInfo != null && certInfo[0] != null) { + val = "<pre>" + certInfo[0].toString() + "</pre>"; + } + } + + valstr = expandValue(prefix + parami + ".value", val); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(name) + "\";\n" + + valstr; // java string already escaped in expandValue. + + arg.set(parami, new RawJS(rawJS)); + } + } + + if (name.equalsIgnoreCase(IRequest.REQUESTOR_PHONE) + || name.equalsIgnoreCase(IRequest.REQUESTOR_EMAIL) + || name.equalsIgnoreCase(IRequest.REQUESTOR_COMMENTS) + || name.equalsIgnoreCase(IRequest.RESULT) + || name.equalsIgnoreCase(IRequest.REQUEST_TRUSTEDMGR_PRIVILEGE)) { + arg.addStringValue(name, req.getExtDataInString(name)); + } + + if (name.equalsIgnoreCase(IRequest.REQUESTOR_NAME)) { + String requestorName = req.getExtDataInString(name); + + requestorName = requestorName.trim(); + if (requestorName.length() > 0) { + arg.addStringValue(name, requestorName); + } + } + + if (name.equalsIgnoreCase(IRequest.ERRORS)) { + Vector<String> errorStrings = req.getExtDataInStringVector(name); + if (errorStrings != null) { + StringBuffer errInfo = new StringBuffer(); + + for (int i = 0; i < errorStrings.size(); i++) { + errInfo.append(errorStrings.elementAt(i)); + errInfo.append("\n"); + } + arg.addStringValue(IRequest.ERRORS, errInfo.toString()); + } + } + if (name.equalsIgnoreCase(IRequest.ERROR)) { + arg.addStringValue(IRequest.ERRORS, req.getExtDataInString(name)); + } + + if (name.equalsIgnoreCase(IRequest.CERT_INFO)) { + // Get the certificate info from the request + X509CertInfo[] certInfo = + req.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + if (certInfo != null && certInfo[0] != null) { + // Get the subject name if any set. + CertificateSubjectName subjectName = null; + String signatureAlgorithm = null; + String signatureAlgorithmName = null; + + try { + subjectName = (CertificateSubjectName) certInfo[0].get(X509CertInfo.SUBJECT); + } catch (IOException e) { + // XXX raise exception + } catch (CertificateException e) { + // XXX raise exception + } + if (subjectName != null) { + String sn; + + try { + sn = subjectName.toString(); + } catch (java.lang.IllegalArgumentException e) { + sn = "* * Malformed Subject Name * *"; + } + String subjectnamevalue = sn; + + arg.addStringValue("subject", subjectnamevalue); + } + + if (mDetails) { + try { + CertificateAlgorithmId certAlgId = (CertificateAlgorithmId) + certInfo[0].get(X509CertInfo.ALGORITHM_ID); + AlgorithmId algId = (AlgorithmId) + certAlgId.get(CertificateAlgorithmId.ALGORITHM); + + signatureAlgorithm = (algId.getOID()).toString(); + signatureAlgorithmName = algId.getName(); + } catch (Exception e) { + // XXX raise exception + } + if (signatureAlgorithm != null) { + arg.addStringValue("signatureAlgorithm", signatureAlgorithm); + } + if (signatureAlgorithmName != null) { + arg.addStringValue("signatureAlgorithmName", signatureAlgorithmName); + } + + CertificateExtensions extensions = null; + + try { + extensions = (CertificateExtensions) certInfo[0].get(X509CertInfo.EXTENSIONS); + } catch (Exception e) { + } + if (extensions != null) { + Enumeration<Extension> exts = extensions.getAttributes(); + + while (exts.hasMoreElements()) { + Extension ext = exts.nextElement(); + + // only know about ns cert type + if (ext instanceof NSCertTypeExtension) { + NSCertTypeExtension nsExtensions = + (NSCertTypeExtension) ext; + + try { + arg.addStringValue("ext_" + NSCertTypeExtension.SSL_SERVER, + nsExtensions.get(NSCertTypeExtension.SSL_SERVER).toString()); + + arg.addStringValue("ext_" + NSCertTypeExtension.SSL_CLIENT, + nsExtensions.get(NSCertTypeExtension.SSL_CLIENT).toString()); + + arg.addStringValue("ext_" + NSCertTypeExtension.EMAIL, + nsExtensions.get(NSCertTypeExtension.EMAIL).toString()); + + arg.addStringValue("ext_" + NSCertTypeExtension.OBJECT_SIGNING, + nsExtensions.get(NSCertTypeExtension.OBJECT_SIGNING).toString()); + + arg.addStringValue("ext_" + NSCertTypeExtension.SSL_CA, + nsExtensions.get(NSCertTypeExtension.SSL_CA).toString()); + + arg.addStringValue("ext_" + NSCertTypeExtension.EMAIL_CA, + nsExtensions.get(NSCertTypeExtension.EMAIL_CA).toString()); + + arg.addStringValue("ext_" + NSCertTypeExtension.OBJECT_SIGNING_CA, + nsExtensions.get(NSCertTypeExtension.OBJECT_SIGNING_CA).toString()); + + } catch (Exception e) { + } + } else if (ext instanceof BasicConstraintsExtension) { + BasicConstraintsExtension bcExt = + (BasicConstraintsExtension) ext; + Integer pathLength = null; + Boolean isCA = null; + + try { + pathLength = (Integer) bcExt.get(BasicConstraintsExtension.PATH_LEN); + isCA = (Boolean) bcExt.get(BasicConstraintsExtension.IS_CA); + } catch (IOException e) { + } + if (pathLength != null) + arg.addIntegerValue("pathLenBasicConstraints", pathLength.intValue()); + if (isCA != null) + arg.addBooleanValue("isCABasicConstraints", isCA.booleanValue()); + } // pretty print all others. + else { + if (argSet != null) { + IArgBlock rr = CMS.createArgBlock(); + + rr.addStringValue( + EXT_PRETTYPRINT, + CMS.getExtPrettyPrint(ext, 0).toString()); + argSet.addRepeatRecord(rr); + } + } + } + + } + + // Get the public key + CertificateX509Key certKey = null; + + try { + certKey = (CertificateX509Key) certInfo[0].get(X509CertInfo.KEY); + } catch (IOException e) { + // XXX raise exception + } catch (CertificateException e) { + // XXX raise exception + } + + X509Key key = null; + + try { + key = (X509Key) certKey.get(CertificateX509Key.KEY); + } catch (IOException e) { + // XXX raise exception + } + + if (key != null) { + arg.addStringValue("subjectPublicKeyInfo", + key.getAlgorithm() + " - " + key.getAlgorithmId().getOID().toString()); + arg.addStringValue("subjectPublicKey", + pp.toHexString(key.getKey(), 0, 16)); + } + + // Get the validity period + CertificateValidity validity = null; + + try { + validity = + (CertificateValidity) + certInfo[0].get(X509CertInfo.VALIDITY); + if (validity != null) { + long validityLength = (((Date) validity.get(CertificateValidity.NOT_AFTER)).getTime() - + ((Date) validity.get(CertificateValidity.NOT_BEFORE)).getTime()) / 1000; + arg.addLongValue("validityLength", validityLength); + } + } catch (IOException e) { + // XXX raise exception + } catch (CertificateException e) { + // XXX raise exception + } + } + } + } + + if (name.equalsIgnoreCase(IRequest.OLD_SERIALS) && mDetails) { + BigInteger oldSerialNo[] = req.getExtDataInBigIntegerArray(IRequest.OLD_SERIALS); + + if (oldSerialNo != null) { + if (argSet != null) { + for (int i = 0; i < oldSerialNo.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + oldSerialNo[i], 16); + argSet.addRepeatRecord(rarg); + } + } + } + } + + if (name.equalsIgnoreCase(IRequest.ISSUED_CERTS) && mDetails && + (req.getRequestStatus().toString().equals(RequestStatus.COMPLETE_STRING) || + req.getRequestType().equals(IRequest.GETREVOCATIONINFO_REQUEST))) { + X509CertImpl issuedCert[] = + req.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + arg.addBigIntegerValue("serialNumber", issuedCert[0].getSerialNumber(), 16); + // Set Serial No for 2nd certificate + if (issuedCert.length == 2) + arg.addBigIntegerValue("serialNumber2", issuedCert[1].getSerialNumber(), 16); + } + if (name.equalsIgnoreCase(IRequest.OLD_CERTS) && mDetails) { + X509CertImpl oldCert[] = + req.getExtDataInCertArray(IRequest.OLD_CERTS); + + if (oldCert != null && oldCert.length > 0) { + arg.addBigIntegerValue("serialNumber", oldCert[0].getSerialNumber(), 16); + arg.addStringValue("subject", oldCert[0].getSubjectDN().toString()); + if (req.getRequestType().equals(IRequest.GETCERTS_REQUEST)) { + for (int i = 0; i < oldCert.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + oldCert[i].getSerialNumber(), 16); + argSet.addRepeatRecord(rarg); + } + } + } + } + + if (name.equalsIgnoreCase(IRequest.CACERTCHAIN) && mDetails) { + byte[] certChainData = req.getExtDataInByteArray( + IRequest.CACERTCHAIN); + if (certChainData != null) { + CertificateChain certChain = new CertificateChain(); + try { + certChain.decode(new ByteArrayInputStream(certChainData)); + + X509Certificate cert[] = certChain.getChain(); + + for (int i = 0; i < cert.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + cert[i].getSerialNumber(), 16); + argSet.addRepeatRecord(rarg); + } + } catch (IOException e) { + // XXX + } + } + } + if (name.equalsIgnoreCase(IRequest.FINGERPRINTS) && mDetails) { + Hashtable<String, String> fingerprints = + req.getExtDataInHashtable(IRequest.FINGERPRINTS); + + if (fingerprints != null) { + String namesAndHashes = null; + Enumeration<String> enumFingerprints = fingerprints.keys(); + + while (enumFingerprints.hasMoreElements()) { + String hashname = enumFingerprints.nextElement(); + String hashvalue = fingerprints.get(hashname); + byte[] fingerprint = CMS.AtoB(hashvalue); + String ppFingerprint = pp.toHexString(fingerprint, 0); + + if (hashname != null && ppFingerprint != null) { + if (namesAndHashes != null) { + namesAndHashes += "+" + hashname + "+" + ppFingerprint; + } else { + namesAndHashes = hashname + "+" + ppFingerprint; + } + } + } + if (namesAndHashes != null) { + arg.addStringValue("fingerprints", namesAndHashes); + } + } + } + } + } + + /** + * print value out nicely in request attributes. + */ + protected String expandValue(String valuename, Object v) { + try { + String valstr = ""; + + // if it's a vector + if (v instanceof Vector) { + valstr = valuename + "= new Array"; + int j = 0; + + StringBuffer sb = new StringBuffer(); + for (@SuppressWarnings("unchecked") + Enumeration<String> n = ((Vector<String>) v).elements(); n.hasMoreElements(); j++) { + sb.append(";\n"); + sb.append(valuename); + sb.append(LB); + sb.append(j); + sb.append(RB); + sb.append(EQ); + sb.append("\""); + sb.append( + CMSTemplate.escapeJavaScriptStringHTML( + n.nextElement().toString())); + sb.append("\";\n"); + } + sb.append("\n"); + valstr = sb.toString(); + return valstr; + } + + // if an array. + int len = -1; + + try { + len = Array.getLength(v); + } catch (IllegalArgumentException e) { + } + if (len >= 0) { // is an array; access each object in array. + valstr = valuename + "= new Array"; + int i; + + for (i = 0; i < len; i++) { + if (Array.get(v, i) != null) + valstr += ";\n" + valuename + LB + i + RB + EQ + "\"" + + CMSTemplate.escapeJavaScriptStringHTML( + Array.get(v, i).toString()) + "\";\n"; + } + return valstr; + } + } catch (Throwable e) { + } + + // if string or unrecognized type, just call its toString method. + return valuename + "=\"" + + CMSTemplate.escapeJavaScriptStringHTML(v.toString()) + "\""; + } + + public String getRequestorDN(IRequest request) { + try { + X509CertInfo info = (X509CertInfo) + request.getExtDataInCertInfo(IEnrollProfile.REQUEST_CERTINFO); + // retrieve the subject name + CertificateSubjectName sn = (CertificateSubjectName) + info.get(X509CertInfo.SUBJECT); + + return sn.toString(); + } catch (Exception e) { + CMS.debug("CertReqParser: getRequestorDN " + e.toString()); + } + return null; + } + + public String getKeyID(IRequest request) { + try { + String kid = null; + + String cid = request.getExtDataInString(IRequest.NETKEY_ATTR_CUID); + if (cid == null) { + cid = ""; + } + String uid = request.getExtDataInString(IRequest.NETKEY_ATTR_USERID); + if (uid == null) { + uid = ""; + } + kid = cid + ":" + uid; + if (kid.equals(":")) { + kid = ""; + } + + return kid; + } catch (Exception e) { + CMS.debug("CertReqParser: getKeyID " + e.toString()); + } + return null; + } + + private void fillRevokeRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg) + throws EBaseException { + // fill in the standard attributes + super.fillRequestIntoArg(l, req, argSet, arg); + + arg.addStringValue("certExtsEnabled", "yes"); + String profile = req.getExtDataInString("profile"); + + //CMS.debug("CertReqParser: profile=" + profile); + if (profile != null) { + arg.addStringValue("profile", profile); + String requestorDN = getRequestorDN(req); + + if (requestorDN != null) { + arg.addStringValue("subject", requestorDN); + } + } else { + arg.addStringValue("profile", "false"); + String keyID = getKeyID(req); + + if (keyID != null) { + arg.addStringValue("subject", keyID); + } + } + + int saCounter = 0; + Enumeration<String> enum1 = req.getExtDataKeys(); + + // gross hack + String prefix = "record."; + + if (argSet.getHeader() == arg) + prefix = "header."; + + while (enum1.hasMoreElements()) { + String name = (String) enum1.nextElement(); + + if (mDetails) { + // show all http parameters stored in request. + if (name.equalsIgnoreCase(IRequest.HTTP_PARAMS)) { + Hashtable<String, String> http_params = req.getExtDataInHashtable(name); + // show certType specially + String certType = http_params.get(IRequest.CERT_TYPE); + + if (certType != null) { + arg.addStringValue(IRequest.CERT_TYPE, certType); + } + // show all http parameters in request + int counter = 0; + Enumeration<String> elms = http_params.keys(); + + while (elms.hasMoreElements()) { + String parami = + IRequest.HTTP_PARAMS + LB + String.valueOf(counter++) + RB; + // hack + String n = (String) elms.nextElement(); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(n) + "\";\n\r" + + prefix + parami + ".value=\"" + + CMSTemplate.escapeJavaScriptStringHTML( + http_params.get(n).toString()) + "\""; + + arg.set(parami, new RawJS(rawJS)); + } + } // show all http headers stored in request. + else if (name.equalsIgnoreCase(IRequest.HTTP_HEADERS)) { + Hashtable<String, String> http_hdrs = req.getExtDataInHashtable(name); + Enumeration<String> elms = http_hdrs.keys(); + int counter = 0; + + while (elms.hasMoreElements()) { + String parami = + IRequest.HTTP_HEADERS + LB + String.valueOf(counter++) + RB; + // hack + String n = elms.nextElement(); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(n) + "\";\n\r" + + prefix + parami + ".value=\"" + + CMSTemplate.escapeJavaScriptStringHTML( + http_hdrs.get(n).toString()) + "\""; + + arg.set(parami, new RawJS(rawJS)); + } + } // show all auth token stored in request. + else if (name.equalsIgnoreCase(IRequest.AUTH_TOKEN)) { + IAuthToken auth_token = req.getExtDataInAuthToken(name); + Enumeration<String> elms = auth_token.getElements(); + int counter = 0; + + while (elms.hasMoreElements()) { + String parami = + IRequest.AUTH_TOKEN + LB + String.valueOf(counter++) + RB; + // hack + String n = (String) elms.nextElement(); + String v = + expandValue(prefix + parami + ".value", + auth_token.getInString(n)); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(n) + "\";\n" + v; + + arg.set(parami, new RawJS(rawJS)); + } + } // all others are request attrs from policy or internal modules. + else { + Object val; + if (req.isSimpleExtDataValue(name)) { + val = req.getExtDataInString(name); + } else { + val = req.getExtDataInStringArray(name); + if (val == null) { + val = req.getExtDataInHashtable(name); + } + } + String valstr = ""; + // hack + String parami = + IRequest.SERVER_ATTRS + LB + String.valueOf(saCounter++) + RB; + + valstr = expandValue(prefix + parami + ".value", val); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(name) + "\";\n" + + valstr; // java string already escaped in expandValue. + + arg.set(parami, new RawJS(rawJS)); + } + } + + if (name.equalsIgnoreCase(IRequest.REQUESTOR_PHONE) + || name.equalsIgnoreCase(IRequest.REQUESTOR_EMAIL) + || name.equalsIgnoreCase(IRequest.REQUESTOR_COMMENTS) + || name.equalsIgnoreCase(IRequest.RESULT) + || name.equalsIgnoreCase(IRequest.REQUEST_TRUSTEDMGR_PRIVILEGE)) { + arg.addStringValue(name, req.getExtDataInString(name)); + } + + if (name.equalsIgnoreCase(IRequest.REQUESTOR_NAME)) { + String requestorName = req.getExtDataInString(name); + + requestorName = requestorName.trim(); + if (requestorName.length() > 0) { + arg.addStringValue(name, requestorName); + } + } + + if (name.equalsIgnoreCase(IRequest.ERRORS)) { + Vector<String> errorsVector = req.getExtDataInStringVector(name); + if (errorsVector != null) { + StringBuffer errInfo = new StringBuffer(); + + for (int i = 0; i < errorsVector.size(); i++) { + errInfo.append(errorsVector.elementAt(i)); + errInfo.append("\n"); + } + arg.addStringValue(IRequest.ERRORS, errInfo.toString()); + } + } + if (name.equalsIgnoreCase(IRequest.ERROR)) { + arg.addStringValue(IRequest.ERRORS, req.getExtDataInString(name)); + } + + if (name.equalsIgnoreCase(IRequest.CERT_INFO)) { + // Get the certificate info from the request + RevokedCertImpl revokedCert[] = req.getExtDataInRevokedCertArray(IRequest.CERT_INFO); + + if (mDetails && revokedCert != null) { + if (argSet != null) { + for (int i = 0; i < revokedCert.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + revokedCert[i].getSerialNumber(), 16); + + CRLExtensions crlExtensions = revokedCert[i].getExtensions(); + + if (crlExtensions != null) { + for (int k = 0; k < crlExtensions.size(); k++) { + Extension ext = (Extension) crlExtensions.elementAt(k); + + if (ext instanceof CRLReasonExtension) { + rarg.addStringValue("reason", + ((CRLReasonExtension) ext).getReason().toString()); + } + } + } else { + rarg.addStringValue("reason", + RevocationReason.UNSPECIFIED.toString()); + } + + argSet.addRepeatRecord(rarg); + } + } else { + arg.addBigIntegerValue("serialNumber", + revokedCert[0].getSerialNumber(), 16); + } + } + } + + if (name.equalsIgnoreCase(IRequest.OLD_SERIALS) && mDetails) { + BigInteger oldSerialNo[] = req.getExtDataInBigIntegerArray(IRequest.OLD_SERIALS); + + if (oldSerialNo != null) { + if (argSet != null) { + for (int i = 0; i < oldSerialNo.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + oldSerialNo[i], 16); + argSet.addRepeatRecord(rarg); + } + } + } + } + + if (name.equalsIgnoreCase(IRequest.OLD_CERTS) && mDetails) { + //X509CertImpl oldCert[] = + // (X509CertImpl[])req.get(IRequest.OLD_CERTS); + Certificate oldCert[] = + (Certificate[]) req.getExtDataInCertArray(IRequest.OLD_CERTS); + + if (oldCert != null && oldCert.length > 0) { + if (oldCert[0] instanceof X509CertImpl) { + X509CertImpl xcert = (X509CertImpl) oldCert[0]; + + arg.addBigIntegerValue("serialNumber", xcert.getSerialNumber(), 16); + arg.addStringValue("subject", xcert.getSubjectDN().toString()); + if (req.getRequestType().equals(IRequest.GETCERTS_REQUEST)) { + for (int i = 0; i < oldCert.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + xcert = (X509CertImpl) oldCert[i]; + rarg.addBigIntegerValue("serialNumber", + xcert.getSerialNumber(), 16); + argSet.addRepeatRecord(rarg); + } + } + } + } + } + + if (name.equalsIgnoreCase(IRequest.REVOKED_CERTS) && mDetails && + req.getRequestType().equals("getRevocationInfo")) { + RevokedCertImpl revokedCert[] = + req.getExtDataInRevokedCertArray(IRequest.REVOKED_CERTS); + + if (revokedCert != null && revokedCert[0] != null) { + boolean reasonFound = false; + CRLExtensions crlExtensions = revokedCert[0].getExtensions(); + + for (int k = 0; k < crlExtensions.size(); k++) { + Extension ext = (Extension) crlExtensions.elementAt(k); + + if (ext instanceof CRLReasonExtension) { + arg.addStringValue("reason", + ((CRLReasonExtension) ext).getReason().toString()); + reasonFound = true; + } + } + if (reasonFound == false) { + arg.addStringValue("reason", "unknown"); + } + } + } + } + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/request/CheckRequest.java b/base/common/src/com/netscape/cms/servlet/request/CheckRequest.java new file mode 100644 index 000000000..b65c90fca --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/CheckRequest.java @@ -0,0 +1,621 @@ +// --- 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.request; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.Locale; +import java.util.StringTokenizer; +import java.math.BigInteger; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.pkcs.PKCS7; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertImpl; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.asn1.INTEGER; +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.crypto.SignatureAlgorithm; +import org.mozilla.jss.pkix.cmc.CMCStatusInfo; +import org.mozilla.jss.pkix.cmc.PKIData; +import org.mozilla.jss.pkix.cmc.ResponseBody; +import org.mozilla.jss.pkix.cmc.TaggedAttribute; +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.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.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Check the status of a certificate request + * + * @version $Revision$, $Date$ + */ +public class CheckRequest extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = 2791195859767119636L; + // constants + public static String FULL_RESPONSE = "cmcFullEnrollmentResponse"; + private final static String INFO = "CheckRequest"; + private final static String REQ_ID = "requestId"; + private final static String REQ_TYPE = "requestType"; + private final static String STATUS = "status"; + private final static String CREATE_ON = "createdOn"; + private final static String UPDATE_ON = "updatedOn"; + private final static String UPDATE_BY = "updatedBy"; + + private final static String TPL_FILE = "requestStatus.template"; + + // variables + private IRequestQueue mQueue = null; + private String mFormPath = null; + private String mAuthorityId = null; + + public CMSRequest newCMSRequest() { + return new CMSRequest(); + } + + /** + * Constructs request query servlet. + */ + public CheckRequest() + throws EBaseException { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "requestStatus.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mQueue = mAuthority.getRequestQueue(); + mAuthorityId = mAuthority.getId(); + mFormPath = "/" + mAuthorityId + "/" + TPL_FILE; + + mTemplates.remove(CMSRequest.SUCCESS); + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param requestId ID of the request to check + * <li>http.param format if 'id', then check the request based on the request ID parameter. If set to CMC, then use + * the 'queryPending' parameter. + * <li>http.param queryPending query formatted as a CMC request + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + CMS.debug("checkRequest: in process!"); + SET transIds = null, sNonces = null; + boolean isCMCReq = false; + INTEGER bodyPartId = null; + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "read"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + // Note error is covered in the same template as success. + EBaseException error = null; + + String requestId = req.getParameter("requestId"); + String format = req.getParameter("format"); + + CMS.debug("checkRequest: requestId " + requestId); + + // They may check the status using CMC queryPending + String queryPending = req.getParameter("queryPending"); + + if (format != null && format.equals("cmc") && queryPending != null && !queryPending.equals("")) { + try { + isCMCReq = true; + byte[] cmcBlob = CMS.AtoB(queryPending); + ByteArrayInputStream cmcBlobIn = + new ByteArrayInputStream(cmcBlob); + + org.mozilla.jss.pkix.cms.ContentInfo cii = (org.mozilla.jss.pkix.cms.ContentInfo) + org.mozilla.jss.pkix.cms.ContentInfo.getTemplate().decode(cmcBlobIn); + SignedData cmcFullReq = (SignedData) + cii.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 controlSequence = pkiData.getControlSequence(); + int numControls = controlSequence.size(); + + for (int i = 0; i < numControls; i++) { + // decode message. + TaggedAttribute taggedAttr = (TaggedAttribute) controlSequence.elementAt(i); + OBJECT_IDENTIFIER type = taggedAttr.getType(); + + if (type.equals(OBJECT_IDENTIFIER.id_cmc_QueryPending)) { + bodyPartId = taggedAttr.getBodyPartID(); + SET requestIds = taggedAttr.getValues(); + int numReq = requestIds.size(); + + // We only process one for now. + if (numReq > 0) { + OCTET_STRING reqId = (OCTET_STRING) + ASN1Util.decode(OCTET_STRING.getTemplate(), + ASN1Util.encode(requestIds.elementAt(0))); + + requestId = new String(reqId.toByteArray()); + } + } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_transactionId)) { + transIds = taggedAttr.getValues(); + } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_recipientNonce)) { + // recipient nonce + } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_senderNonce)) { + sNonces = taggedAttr.getValues(); + } + } + } catch (Exception e) { + error = new EBaseException(e.toString()); + } + } + + IArgBlock httpParams = cmsReq.getHttpParams(); + boolean importCert = httpParams.getValueAsBoolean("importCert", + false); + // xxx need to check why this is not available at startup + X509Certificate mCACerts[] = null; + + try { + mCACerts = ((ICertAuthority) mAuthority).getCACertChain().getChain(); + } catch (Exception e) { + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CA_CHAIN_NOT_AVAILABLE")); + } + + if (requestId == null || requestId.trim().equals("")) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_NO_REQUEST_ID_PROVIDED")); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_REQUEST_ID_PROVIDED")); + } + try { + new BigInteger(requestId); + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT_1", requestId)); + throw new EBaseException( + CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT_1", requestId)); + } + + IRequest r = mQueue.findRequest(new RequestId(requestId)); + + if (r == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_REQUEST_ID_NOT_FOUND_1", requestId)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_REQUEST_ID_NOT_FOUND", requestId)); + } + + if (authToken != null) { + // if RA, requestOwner must match the group + String group = authToken.getInString("group"); + if ((group != null) && (group != "")) { + if (group.equals("Registration Manager Agents")) { + boolean groupMatched = false; + String requestOwner = r.getExtDataInString("requestOwner"); + if (requestOwner != null) { + if (requestOwner.equals(group)) + groupMatched = true; + } + if (groupMatched == false) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT_1", requestId.toString())); + throw new EBaseException( + CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT_1", requestId)); + } + } + } + } + + RequestStatus status = r.getRequestStatus(); + String note = r.getExtDataInString("requestNotes"); + + header.addStringValue("authority", mAuthorityId); + header.addLongValue(REQ_ID, Long.parseLong(r.getRequestId().toString())); + header.addStringValue(STATUS, status.toString()); + header.addLongValue(CREATE_ON, r.getCreationTime().getTime() / 1000); + header.addLongValue(UPDATE_ON, r.getModificationTime().getTime() / 1000); + if (note != null && note.length() > 0) + header.addStringValue("requestNotes", note); + + String type = r.getRequestType(); + Integer result = r.getExtDataInInteger(IRequest.RESULT); + + /* if (type.equals(IRequest.ENROLLMENT_REQUEST) && (r.get("profile") != null) && status.equals(RequestStatus.COMPLETE)) { + X509CertImpl cert = (X509CertImpl) r.get(IEnrollProfile.REQUEST_ISSUED_CERT); + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + cert.getSerialNumber(), 16); + argSet.addRepeatRecord(rarg); + } + */ + String profileId = r.getExtDataInString("profileId"); + if (profileId != null) { + result = IRequest.RES_SUCCESS; + } + if ((type != null) && (type.equals(IRequest.ENROLLMENT_REQUEST) || + type.equals(IRequest.RENEWAL_REQUEST)) && (status != null) && + status.equals(RequestStatus.COMPLETE) && (result != null) && + result.equals(IRequest.RES_SUCCESS)) { + Object o = r.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + if (profileId != null) { + X509CertImpl impl[] = new X509CertImpl[1]; + impl[0] = r.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT); + o = impl; + } + if (o != null && (o instanceof X509CertImpl[])) { + X509CertImpl[] certs = (X509CertImpl[]) o; + + if (certs != null && certs.length > 0) { + for (int i = 0; i < certs.length; i++) { + if (certs[i] != null) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + certs[i].getSerialNumber(), 16); + // add pkcs7 cert for importing + if (importCert || isCMCReq) { + //byte[] ba = certs[i].getEncoded(); + X509CertImpl[] certsInChain = new X509CertImpl[1]; + ; + if (mCACerts != null) { + for (int ii = 0; ii < mCACerts.length; ii++) { + if (certs[i].equals(mCACerts[ii])) { + certsInChain = new + X509CertImpl[mCACerts.length]; + break; + } + certsInChain = new X509CertImpl[mCACerts.length + 1]; + } + } + + // Set the EE cert + certsInChain[0] = certs[i]; + + // Set the Ca certificate chain + if (mCACerts != null) { + for (int ii = 0; ii < mCACerts.length; ii++) { + if (!certs[i].equals(mCACerts[ii])) + certsInChain[ii + 1] = (X509CertImpl) mCACerts[ii]; + } + } + // Wrap the chain into a degenerate P7 object + String p7Str; + + try { + PKCS7 p7 = new PKCS7(new AlgorithmId[0], + new netscape.security.pkcs.ContentInfo(new byte[0]), + certsInChain, + new netscape.security.pkcs.SignerInfo[0]); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + p7.encodeSignedData(bos); + byte[] p7Bytes = bos.toByteArray(); + + p7Str = CMS.BtoA(p7Bytes); + + StringTokenizer tokenizer = null; + + if (File.separator.equals("\\")) { + char[] nl = new char[2]; + + nl[0] = 10; + nl[1] = 13; + String nlstr = new String(nl); + + tokenizer = new StringTokenizer(p7Str, nlstr); + } else + tokenizer = new StringTokenizer(p7Str, "\n"); + StringBuffer res = new StringBuffer(); + + while (tokenizer.hasMoreTokens()) { + String elem = (String) tokenizer.nextToken(); + + res.append(elem); + } + + header.addStringValue("pkcs7ChainBase64", res.toString()); + + // compose full response + if (isCMCReq) { + SEQUENCE controlSeq = new SEQUENCE(); + int bpid = 1; + SEQUENCE bpids = new SEQUENCE(); + + if (bodyPartId != null) + bpids.addElement(bodyPartId); + CMCStatusInfo cmcStatusInfo = new + CMCStatusInfo(CMCStatusInfo.SUCCESS, bpids); + TaggedAttribute ta = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, + cmcStatusInfo); + + controlSeq.addElement(ta); + + // copy transactionID, senderNonce, + // create recipientNonce + if (transIds != null) { + ta = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_transactionId, + transIds); + controlSeq.addElement(ta); + } + + if (sNonces != null) { + ta = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_recipientNonce, + sNonces); + controlSeq.addElement(ta); + } + + String salt = CMSServlet.generateSalt(); + byte[] dig; + + try { + MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1"); + + dig = SHA1Digest.digest(salt.getBytes()); + } catch (NoSuchAlgorithmException ex) { + dig = salt.getBytes(); + } + String b64E = CMS.BtoA(dig); + String[] newNonce = { b64E }; + + ta = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_senderNonce, + new OCTET_STRING(newNonce[0].getBytes())); + controlSeq.addElement(ta); + + ResponseBody rb = new ResponseBody(controlSeq, new + SEQUENCE(), new + SEQUENCE()); + EncapsulatedContentInfo ci = new + EncapsulatedContentInfo(OBJECT_IDENTIFIER.id_cct_PKIResponse, + rb); + + org.mozilla.jss.crypto.X509Certificate x509cert = null; + + if (mAuthority instanceof ICertificateAuthority) { + x509cert = ((ICertificateAuthority) mAuthority).getCaX509Cert(); + } else if (mAuthority instanceof IRegistrationAuthority) { + x509cert = ((IRegistrationAuthority) mAuthority).getRACert(); + } + if (x509cert == null) + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_CMC_ERROR", + "No signing cert found.")); + + X509CertImpl cert = new X509CertImpl(x509cert.getEncoded()); + ByteArrayInputStream issuer1 = new + ByteArrayInputStream(((X500Name) cert.getIssuerDN()).getEncoded()); + Name issuer = (Name) Name.getTemplate().decode(issuer1); + IssuerAndSerialNumber ias = + new + IssuerAndSerialNumber(issuer, new INTEGER(cert.getSerialNumber() + .toString())); + SignerIdentifier si = new + SignerIdentifier(SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null); + + // SHA1 is the default digest Alg for now. + DigestAlgorithm digestAlg = null; + SignatureAlgorithm signAlg = null; + org.mozilla.jss.crypto.PrivateKey privKey = + CryptoManager.getInstance().findPrivKeyByCert(x509cert); + org.mozilla.jss.crypto.PrivateKey.Type keyType = privKey.getType(); + + if (keyType.equals(org.mozilla.jss.crypto.PrivateKey.RSA)) + signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest; + else if (keyType.equals(org.mozilla.jss.crypto.PrivateKey.DSA)) + signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest; + MessageDigest SHADigest = null; + byte[] digest = null; + + try { + SHADigest = MessageDigest.getInstance("SHA1"); + digestAlg = DigestAlgorithm.SHA1; + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + + rb.encode((OutputStream) ostream); + digest = SHADigest.digest(ostream.toByteArray()); + } catch (NoSuchAlgorithmException ex) { + //log("digest fail"); + } + + org.mozilla.jss.pkix.cms.SignerInfo signInfo = new + org.mozilla.jss.pkix.cms.SignerInfo(si, null, null, + OBJECT_IDENTIFIER.id_cct_PKIResponse, + digest, signAlg, + privKey); + SET signInfos = new SET(); + + signInfos.addElement(signInfo); + + SET digestAlgs = new SET(); + + if (digestAlg != null) { + AlgorithmIdentifier ai = new + AlgorithmIdentifier(digestAlg.toOID(), + null); + + digestAlgs.addElement(ai); + } + + SET jsscerts = new SET(); + + for (int j = 0; j < certsInChain.length; j++) { + ByteArrayInputStream is = new + ByteArrayInputStream(certsInChain[j].getEncoded()); + org.mozilla.jss.pkix.cert.Certificate certJss = + (org.mozilla.jss.pkix.cert.Certificate) + org.mozilla.jss.pkix.cert.Certificate.getTemplate().decode(is); + + jsscerts.addElement(certJss); + } + + SignedData fResponse = new + SignedData(digestAlgs, ci, + jsscerts, null, signInfos); + org.mozilla.jss.pkix.cms.ContentInfo fullResponse = + new + org.mozilla.jss.pkix.cms.ContentInfo( + org.mozilla.jss.pkix.cms.ContentInfo.SIGNED_DATA, fResponse); + ByteArrayOutputStream ostream = new + ByteArrayOutputStream(); + + fullResponse.encode((OutputStream) ostream); + byte[] fr = ostream.toByteArray(); + + header.addStringValue(FULL_RESPONSE, CMS.BtoA(fr)); + } + } catch (Exception e) { + e.printStackTrace(); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_FORMING_PKCS7_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_FORMING_PKCS7_ERROR")); + } + } + argSet.addRepeatRecord(rarg); + } + } + } + } + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/IReqParser.java b/base/common/src/com/netscape/cms/servlet/request/IReqParser.java new file mode 100644 index 000000000..f90e97b70 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/IReqParser.java @@ -0,0 +1,42 @@ +// --- 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.request; + +import java.util.Locale; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.common.CMSTemplateParams; + +/** + * An interface representing a request parser which + * converts Java request object into name value + * pairs and vice versa. + * <P> + * + * @version $Revision$, $Date$ + */ +public interface IReqParser { + + /** + * Maps request object into argument block. + */ + public void fillRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg) + throws EBaseException; +} diff --git a/base/common/src/com/netscape/cms/servlet/request/KeyReqParser.java b/base/common/src/com/netscape/cms/servlet/request/KeyReqParser.java new file mode 100644 index 000000000..b7ddc16d4 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/KeyReqParser.java @@ -0,0 +1,81 @@ +// --- 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.request; + +import java.math.BigInteger; +import java.util.Locale; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.key.KeyRecordParser; + +/** + * Output a 'pretty print' of a Key Archival request + * + * @version $Revision$, $Date$ + */ +public class KeyReqParser extends ReqParser { + + public static final KeyReqParser PARSER = new KeyReqParser(); + public static final String OUTPUT_SERIALNO = "serialNumber"; + + /** + * Constructs a certificate request parser. + */ + public KeyReqParser() { + } + + /** + * Fills in certificate specific request attributes. + */ + public void fillRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg) + throws EBaseException { + // fill in the standard attributes + super.fillRequestIntoArg(l, req, argSet, arg); + + String type = req.getRequestType(); + + if (type.equals(IRequest.ENROLLMENT_REQUEST)) { + BigInteger recSerialNo = req.getExtDataInBigInteger("keyRecord"); + IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority) CMS.getSubsystem("kra"); + if (kra != null) { + KeyRecordParser.fillRecordIntoArg( + kra.getKeyRepository().readKeyRecord(recSerialNo), + arg); + } else { + throw new EBaseException("KRA is not available"); + } + + } else if (type.equals(IRequest.KEYRECOVERY_REQUEST)) { + BigInteger kid = req.getExtDataInBigInteger("serialNumber"); + + arg.addStringValue(OUTPUT_SERIALNO, kid.toString()); + + // for async recovery + String agents = (String) req.getExtDataInString("approvingAgents"); + arg.addStringValue("approvingAgents", agents); + } else { + System.out.println("Bad Request " + type); + // invalid request + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java b/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java new file mode 100644 index 000000000..cd08f46bb --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java @@ -0,0 +1,69 @@ +package com.netscape.cms.servlet.request; + +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; + +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.request.model.ArchivalRequestData; +import com.netscape.cms.servlet.request.model.KeyRequestInfo; +import com.netscape.cms.servlet.request.model.RecoveryRequestData; + +@Path("/keyrequest") +public interface KeyRequestResource { + public final String SYMMETRIC_KEY_TYPE = "symmetricKey"; + public final String PASS_PHRASE_TYPE = "passPhrase"; + public final String ASYMMETRIC_KEY_TYPE = "asymmetricKey"; + + /** + * Used to retrieve key request info for a specific request + */ + @GET + @Path("{id}") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) + public KeyRequestInfo getRequestInfo(@PathParam("id") RequestId id); + + // Archiving - used to test integration with a browser + @POST + @Path("archive") + @Produces({ MediaType.TEXT_XML }) + @Consumes({ MediaType.APPLICATION_FORM_URLENCODED}) + public KeyRequestInfo archiveKey(MultivaluedMap<String, String> form); + + @POST + @Path("archive") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public KeyRequestInfo archiveKey(ArchivalRequestData data); + + //Recovery - used to test integration with a browser + @POST + @Path("recover") + @Produces({ MediaType.TEXT_XML }) + @Consumes({ MediaType.APPLICATION_FORM_URLENCODED}) + public KeyRequestInfo recoverKey(MultivaluedMap<String, String> form); + + @POST + @Path("recover") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public KeyRequestInfo recoverKey(RecoveryRequestData data); + + @POST + @Path("approve/{id}") + public void approveRequest(@PathParam("id") RequestId id); + + @POST + @Path("reject/{id}") + public void rejectRequest(@PathParam("id") RequestId id); + + @POST + @Path("cancel/{id}") + public void cancelRequest(@PathParam("id") RequestId id); + +} diff --git a/base/common/src/com/netscape/cms/servlet/request/KeyRequestResourceService.java b/base/common/src/com/netscape/cms/servlet/request/KeyRequestResourceService.java new file mode 100644 index 000000000..43e58bbdc --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/KeyRequestResourceService.java @@ -0,0 +1,165 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package com.netscape.cms.servlet.request; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.base.CMSResourceService; +import com.netscape.cms.servlet.request.model.ArchivalRequestData; +import com.netscape.cms.servlet.request.model.KeyRequestDAO; +import com.netscape.cms.servlet.request.model.KeyRequestInfo; +import com.netscape.cms.servlet.request.model.RecoveryRequestData; + +/** + * @author alee + * + */ +public class KeyRequestResourceService extends CMSResourceService implements KeyRequestResource { + + @Context + UriInfo uriInfo; + + /** + * Used to retrieve key request info for a specific request + */ + public KeyRequestInfo getRequestInfo(RequestId id) { + // auth and authz + KeyRequestDAO dao = new KeyRequestDAO(); + KeyRequestInfo info; + try { + info = dao.getRequest(id, uriInfo); + } catch (EBaseException e) { + // log error + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + if (info == null) { + // request does not exist + throw new WebApplicationException(Response.Status.NOT_FOUND); + } + return info; + } + + // Archiving - used to test integration with a browser + public KeyRequestInfo archiveKey(MultivaluedMap<String, String> form) { + ArchivalRequestData data = new ArchivalRequestData(form); + return archiveKey(data); + } + + public KeyRequestInfo archiveKey(ArchivalRequestData data) { + // auth and authz + // Catch this before internal server processing has to deal with it + + if (data == null || data.getClientId() == null + || data.getWrappedPrivateData() == null + || data.getDataType() == null) { + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + + KeyRequestDAO dao = new KeyRequestDAO(); + KeyRequestInfo info; + try { + info = dao.submitRequest(data, uriInfo); + } catch (EBaseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + return info; + } + + //Recovery - used to test integration with a browser + public KeyRequestInfo recoverKey(MultivaluedMap<String, String> form) { + RecoveryRequestData data = new RecoveryRequestData(form); + return recoverKey(data); + } + + public KeyRequestInfo recoverKey(RecoveryRequestData data) { + // auth and authz + + //Check for entirely illegal data combination here + //Catch this before the internal server processing has to deal with it + //If data has been provided, we need at least the wrapped session key, + //or the command is invalid. + if (data == null || (data.getTransWrappedSessionKey() == null + && data.getSessionWrappedPassphrase() != null)) { + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + KeyRequestDAO dao = new KeyRequestDAO(); + KeyRequestInfo info; + try { + info = dao.submitRequest(data, uriInfo); + } catch (EBaseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + return info; + } + + public void approveRequest(RequestId id) { + if (id == null) { + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + // auth and authz + KeyRequestDAO dao = new KeyRequestDAO(); + try { + dao.approveRequest(id); + } catch (EBaseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } + + public void rejectRequest(RequestId id) { + if (id == null) { + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + // auth and authz + KeyRequestDAO dao = new KeyRequestDAO(); + try { + dao.rejectRequest(id); + } catch (EBaseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } + + public void cancelRequest(RequestId id) { + if (id == null) { + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + // auth and authz + KeyRequestDAO dao = new KeyRequestDAO(); + try { + dao.cancelRequest(id); + } catch (EBaseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/KeyRequestsResource.java b/base/common/src/com/netscape/cms/servlet/request/KeyRequestsResource.java new file mode 100644 index 000000000..fd6bc4c27 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/KeyRequestsResource.java @@ -0,0 +1,34 @@ +package com.netscape.cms.servlet.request; + +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.request.model.KeyRequestInfos; + +@Path("/keyrequests") +public interface KeyRequestsResource { + + public static final int DEFAULT_START = 0; + public static final int DEFAULT_PAGESIZE = 20; + public static final int DEFAULT_MAXRESULTS = 100; + public static final int DEFAULT_MAXTIME = 10; + + /** + * Used to generate list of key requests based on the search parameters + */ + @GET + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) + public KeyRequestInfos listRequests(@QueryParam("requestState") String requestState, + @QueryParam("requestType") String requestType, + @QueryParam("clientID") String clientID, + @DefaultValue(""+DEFAULT_START) @QueryParam("start") RequestId start, + @DefaultValue(""+DEFAULT_PAGESIZE) @QueryParam("pageSize") int pageSize, + @DefaultValue(""+DEFAULT_MAXRESULTS) @QueryParam("maxResults") int maxResults, + @DefaultValue(""+DEFAULT_MAXTIME) @QueryParam("maxTime") int maxTime); + +} diff --git a/base/common/src/com/netscape/cms/servlet/request/KeyRequestsResourceService.java b/base/common/src/com/netscape/cms/servlet/request/KeyRequestsResourceService.java new file mode 100644 index 000000000..11898ef7a --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/KeyRequestsResourceService.java @@ -0,0 +1,101 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package com.netscape.cms.servlet.request; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.base.CMSResourceService; +import com.netscape.cms.servlet.request.model.KeyRequestDAO; +import com.netscape.cms.servlet.request.model.KeyRequestInfos; +import com.netscape.cmsutil.ldap.LDAPUtil; + +/** + * @author alee + * + */ +public class KeyRequestsResourceService extends CMSResourceService implements KeyRequestsResource{ + + @Context + UriInfo uriInfo; + + /** + * Used to generate list of key requests based on the search parameters + */ + public KeyRequestInfos listRequests(String requestState, String requestType, String clientID, + RequestId start, int pageSize, int maxResults, int maxTime) { + // auth and authz + + // get ldap filter + String filter = createSearchFilter(requestState, requestType, clientID); + CMS.debug("listRequests: filter is " + filter); + + // get start marker + if (start == null) { + start = new RequestId(KeyRequestsResource.DEFAULT_START); + } + + KeyRequestDAO reqDAO = new KeyRequestDAO(); + KeyRequestInfos requests; + try { + requests = reqDAO.listRequests(filter, start, pageSize, maxResults, maxTime, uriInfo); + } catch (EBaseException e) { + CMS.debug("listRequests: error in obtaining request results" + e); + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + return requests; + } + + private String createSearchFilter(String requestState, String requestType, String clientID) { + String filter = ""; + int matches = 0; + + if ((requestState == null) && (requestType == null) && (clientID == null)) { + filter = "(requeststate=*)"; + return filter; + } + + if (requestState != null) { + filter += "(requeststate=" + LDAPUtil.escape(requestState) + ")"; + matches ++; + } + + if (requestType != null) { + filter += "(requesttype=" + LDAPUtil.escape(requestType) + ")"; + matches ++; + } + + if (clientID != null) { + filter += "(clientID=" + LDAPUtil.escape(clientID) + ")"; + matches ++; + } + + if (matches > 1) { + filter = "(&" + filter + ")"; + } + + return filter; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/ProcessCertReq.java b/base/common/src/com/netscape/cms/servlet/request/ProcessCertReq.java new file mode 100644 index 000000000..820e9a654 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/ProcessCertReq.java @@ -0,0 +1,1933 @@ +// --- 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.request; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.util.Date; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.extensions.NSCertTypeExtension; +import netscape.security.extensions.PresenceServerExtension; +import netscape.security.util.DerValue; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.BasicConstraintsExtension; +import netscape.security.x509.CertificateAlgorithmId; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.CertificateVersion; +import netscape.security.x509.Extension; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertImpl; +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.authority.IAuthority; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.publish.IPublisherProcessor; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.usrgrp.IGroup; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.certsrv.usrgrp.IUser; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.cert.ImportCertsTemplateFiller; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cmsutil.util.Utils; + +/** + * Agent operations on Certificate requests. This servlet is used + * by an Agent to approve, reject, reassign, or change a certificate + * request. + * + * @version $Revision$, $Date$ + */ +public class ProcessCertReq extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 812464895240811318L; + private final static String INFO = "processReq"; + private final static String SEQNUM = "seqNum"; + private final static String TO_DO = "toDo"; + private final static String TPL_FILE = "processCertReq.template"; + + private IRequestQueue mQueue = null; + private String mFormPath = null; + private IReqParser mParser = null; + private IPublisherProcessor mPublisherProcessor = null; + private boolean mExtraAgentParams = false; + + // for RA only since it does not have a database. + private final static String REQ_COMPLETED_TEMPLATE = "ra/RequestCompleted.template"; + private final static String PROP_REQ_COMPLETED_TEMPLATE = "requestCompletedTemplate"; + private final static String PROP_EXTRA_AGENT_PARAMS = "extraAgentParams"; + private static ICMSTemplateFiller REQ_COMPLETED_FILLER = new RAReqCompletedFiller(); + private String mReqCompletedTemplate = null; + private final static String CERT_TYPE = "certType"; + + private String auditServiceID = ILogger.UNIDENTIFIED; + private final static String AGENT_CA_CLONE_ENROLLMENT_SERVLET = + "caProcessCertReq"; + private final static String AGENT_RA_CLONE_ENROLLMENT_SERVLET = + "raProcessCertReq"; + private final static String SIGNED_AUDIT_ACCEPTANCE = "accept"; + private final static String SIGNED_AUDIT_CANCELLATION = "cancel"; + private final static String SIGNED_AUDIT_CLONING = "clone"; + private final static String SIGNED_AUDIT_REJECTION = "reject"; + private final static byte EOL[] = { Character.LINE_SEPARATOR }; + private final static String[] SIGNED_AUDIT_MANUAL_CANCELLATION_REASON = new String[] { + + /* 0 */"manual non-profile cert request cancellation: " + + "request cannot be processed due to an " + + "authorization failure", + + /* 1 */"manual non-profile cert request cancellation: " + + "no reason has been given for cancelling this " + + "cert request", + + /* 2 */"manual non-profile cert request cancellation: " + + "indeterminate reason for inability to process " + + "cert request due to an EBaseException", + + /* 3 */"manual non-profile cert request cancellation: " + + "indeterminate reason for inability to process " + + "cert request due to an IOException", + + /* 4 */"manual non-profile cert request cancellation: " + + "indeterminate reason for inability to process " + + "cert request due to a CertificateException", + + /* 5 */"manual non-profile cert request cancellation: " + + "indeterminate reason for inability to process " + + "cert request due to a NoSuchAlgorithmException" + }; + private final static String[] SIGNED_AUDIT_MANUAL_REJECTION_REASON = new String[] { + + /* 0 */"manual non-profile cert request rejection: " + + "request cannot be processed due to an " + + "authorization failure", + + /* 1 */"manual non-profile cert request rejection: " + + "no reason has been given for rejecting this " + + "cert request", + + /* 2 */"manual non-profile cert request rejection: " + + "indeterminate reason for inability to process " + + "cert request due to an EBaseException", + + /* 3 */"manual non-profile cert request rejection: " + + "indeterminate reason for inability to process " + + "cert request due to an IOException", + + /* 4 */"manual non-profile cert request rejection: " + + "indeterminate reason for inability to process " + + "cert request due to a CertificateException", + + /* 5 */"manual non-profile cert request rejection: " + + "indeterminate reason for inability to process " + + "cert request due to a NoSuchAlgorithmException" + }; + private final static String LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST = + "LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST_5"; + private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5"; + + /** + * Process request. + */ + public ProcessCertReq() + throws EBaseException { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "processCertReq.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + try { + super.init(sc); + + // determine the service ID for signed audit log messages + String id = sc.getInitParameter(CMSServlet.PROP_ID); + + if (id != null) { + if (!(auditServiceID.equals( + AGENT_CA_CLONE_ENROLLMENT_SERVLET)) + && !(auditServiceID.equals( + AGENT_RA_CLONE_ENROLLMENT_SERVLET))) { + auditServiceID = ILogger.UNIDENTIFIED; + } else { + auditServiceID = id.trim(); + } + } + + mQueue = mAuthority.getRequestQueue(); + mPublisherProcessor = + ((ICertAuthority) mAuthority).getPublisherProcessor(); + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + mParser = CertReqParser.DETAIL_PARSER; + + // override success and error templates to null - + // handle templates locally. + mTemplates.remove(CMSRequest.SUCCESS); + + try { + mReqCompletedTemplate = sc.getInitParameter( + PROP_REQ_COMPLETED_TEMPLATE); + if (mReqCompletedTemplate == null) + mReqCompletedTemplate = REQ_COMPLETED_TEMPLATE; + String tmp = sc.getInitParameter(PROP_EXTRA_AGENT_PARAMS); + + if (tmp != null && tmp.trim().equalsIgnoreCase("true")) + mExtraAgentParams = true; + else + mExtraAgentParams = false; + } catch (Exception e) { + // does not happen. + } + } catch (ServletException eAudit1) { + // rethrow caught exception + throw eAudit1; + } + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param seqNum request id + * <li>http.param notValidBefore certificate validity - notBefore - in seconds since jan 1, 1970 + * <li>http.param notValidAfter certificate validity - notAfter - in seconds since jan 1, 1970 + * <li>http.param subject certificate subject name + * <li>http.param toDo requested action (can be one of: clone, reject, accept, cancel) + * <li>http.param signatureAlgorithm certificate signing algorithm + * <li>http.param addExts base-64, DER encoded Extension or SEQUENCE OF Extensions to add to certificate + * <li>http.param pathLenConstraint integer path length constraint to use in BasicConstraint extension if applicable + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + long startTime = CMS.getCurrentDate().getTime(); + String toDo = null; + String subject = null; + String signatureAlgorithm = null; + long notValidBefore = 0; + long notValidAfter = 0; + BigInteger seqNum = BigInteger.ONE.negate(); + EBaseException error = null; + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + try { + if (req.getParameter(SEQNUM) != null) { + CMS.debug( + "ProcessCertReq: parameter seqNum " + req.getParameter(SEQNUM)); + seqNum = new BigInteger(req.getParameter(SEQNUM)); + } + String notValidBeforeStr = req.getParameter("notValidBefore"); + + if (notValidBeforeStr != null && notValidBeforeStr.length() > 0) { + notValidBefore = Long.parseLong(notValidBeforeStr); + notValidBefore *= 1000; + } + String notValidAfterStr = req.getParameter("notValidAfter"); + + if (notValidAfterStr != null && notValidAfterStr.length() > 0) { + notValidAfter = Long.parseLong(notValidAfterStr); + notValidAfter *= 1000; + } + + toDo = req.getParameter("toDo"); + + subject = req.getParameter("subject"); + signatureAlgorithm = req.getParameter("signatureAlgorithm"); + + IRequest r = null; + + if (seqNum.compareTo(BigInteger.ONE.negate()) > 0) { + r = mQueue.findRequest(new RequestId(seqNum)); + } + + if (seqNum.compareTo(BigInteger.ONE.negate()) > 0 && r != null) { + processX509(cmsReq, argSet, header, seqNum, req, resp, + toDo, signatureAlgorithm, subject, + notValidBefore, notValidAfter, locale[0], startTime); + } else { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_REQUEST_ID_1", seqNum.toString())); + error = new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_REQUEST_ID", + seqNum.toString())); + } + } catch (EBaseException e) { + error = e; + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, "Error " + e); + error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT")); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + return; + } + + /** + * Process X509 certificate enrollment request and send request information + * to the caller. + * <P> + * + * (Certificate Request - an "agent" cert request for "cloning") + * <P> + * + * (Certificate Request Processed - either a manual "agent" non-profile based cert acceptance, a manual "agent" + * non-profile based cert cancellation, or a manual "agent" non-profile based cert rejection) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST used when a non-profile cert request is made + * (before approval process) + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + * </ul> + * + * @param cmsReq a certificate enrollment request + * @param argSet CMS template parameters + * @param header argument block + * @param seqNum sequence number + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param toDo string representing the requested action (can be one of: + * clone, reject, accept, cancel) + * @param signatureAlgorithm string containing the signature algorithm + * @param subject string containing the subject name of the certificate + * @param notValidBefore certificate validity - notBefore - in seconds + * since Jan 1, 1970 + * @param notValidAfter certificate validity - notAfter - in seconds since + * Jan 1, 1970 + * @param locale the system locale + * @param startTime the current date + * @exception EBaseException an error has occurred + */ + private void processX509(CMSRequest cmsReq, + CMSTemplateParams argSet, IArgBlock header, + BigInteger seqNum, HttpServletRequest req, + HttpServletResponse resp, + String toDo, String signatureAlgorithm, + String subject, + long notValidBefore, long notValidAfter, + Locale locale, long startTime) + throws EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = ILogger.UNIDENTIFIED; + String auditCertificateSubjectName = subject; + String auditInfoName = auditInfoName(toDo); + String id = null; + + // "normalize" the "auditCertificateSubjectName" + if (auditCertificateSubjectName != null) { + // NOTE: This is ok even if the cert subject name is "" (empty)! + auditCertificateSubjectName = auditCertificateSubjectName.trim(); + } else { + // NOTE: Here, the cert subject name is MISSING, not "" (empty)! + auditCertificateSubjectName = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + try { + IRequest r = mQueue.findRequest(new RequestId(seqNum)); + + if (r != null) { + // overwrite "auditRequesterID" if and only if "id" != null + id = r.getRequestId().toString(); + if (id != null) { + auditRequesterID = id.trim(); + } + } + + if (mAuthority != null) + header.addStringValue("authorityid", mAuthority.getId()); + + if (toDo != null) { + // for audit log + IAuthToken authToken = authenticate(cmsReq); + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "execute"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", + e.toString())); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", + e.toString())); + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + + // store a message in the signed audit log file + if (toDo.equals(SIGNED_AUDIT_CLONING)) { + // ("agent" cert request for "cloning") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) { + // (manual "agent" cert request processed - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) { + // (manual "agent" cert request processed - "cancelled") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[0]); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) { + // (manual "agent" cert request processed - "rejected") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_REJECTION_REASON[0]); + + audit(auditMessage); + } + + return; + } + + String authMgr = AuditFormat.NOAUTH; + + if (authToken != null) { + authMgr = + authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + } + String agentID = authToken.getInString("userid"); + String initiative = AuditFormat.FROMAGENT + " agentID: " + agentID; + + // Get the certificate info from the request + X509CertInfo certInfo[] = r.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + header.addStringValue("toDo", toDo); + if (toDo.equals("accept")) { + + if (certInfo != null) { + int alterationCounter = 0; + + for (int i = 0; i < certInfo.length; i++) { + CertificateAlgorithmId certAlgId = + (CertificateAlgorithmId) + certInfo[i].get(X509CertInfo.ALGORITHM_ID); + + AlgorithmId algId = (AlgorithmId) + certAlgId.get(CertificateAlgorithmId.ALGORITHM); + + if (!(algId.getName().equals(signatureAlgorithm))) { + alterationCounter++; + AlgorithmId newAlgId = AlgorithmId.getAlgorithmId(signatureAlgorithm); + + certInfo[i].set(X509CertInfo.ALGORITHM_ID, + new CertificateAlgorithmId(newAlgId)); + } + + CertificateSubjectName certSubject = + (CertificateSubjectName) + certInfo[i].get(X509CertInfo.SUBJECT); + + if (subject != null && + !(certSubject.toString().equals(subject))) { + + alterationCounter++; + certInfo[i].set(X509CertInfo.SUBJECT, + new CertificateSubjectName( + (new X500Name(subject)))); + } + + CertificateValidity certValidity = + (CertificateValidity) + certInfo[i].get(X509CertInfo.VALIDITY); + Date currentTime = CMS.getCurrentDate(); + boolean validityChanged = false; + + // only override these values if agent specified them + if (notValidBefore > 0) { + Date notBefore = (Date) certValidity.get( + CertificateValidity.NOT_BEFORE); + + if (notBefore.getTime() == 0 || + notBefore.getTime() != notValidBefore) { + Date validFrom = new Date(notValidBefore); + + notBefore = (notValidBefore == 0) ? currentTime : validFrom; + certValidity.set(CertificateValidity.NOT_BEFORE, + notBefore); + validityChanged = true; + } + } + if (notValidAfter > 0) { + Date validTo = new Date(notValidAfter); + Date notAfter = (Date) + certValidity.get(CertificateValidity.NOT_AFTER); + + if (notAfter.getTime() == 0 || + notAfter.getTime() != notValidAfter) { + notAfter = currentTime; + notAfter = (notValidAfter == 0) ? currentTime : validTo; + certValidity.set(CertificateValidity.NOT_AFTER, + notAfter); + validityChanged = true; + } + } + if (validityChanged) { + // this set() trigger this rebuild of internal + // raw der encoding cache of X509CertInfo. + // Otherwise, the above change wont have effect. + certInfo[i].set(X509CertInfo.VALIDITY, certValidity); + } + + if (certInfo[i].get(X509CertInfo.VERSION) == null) { + certInfo[i].set(X509CertInfo.VERSION, + new CertificateVersion( + CertificateVersion.V3)); + } + + CertificateExtensions extensions = null; + + try { + extensions = (CertificateExtensions) + certInfo[i].get(X509CertInfo.EXTENSIONS); + } catch (Exception e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_PARSING_EXTENS", e.toString())); + } + + // 99/08/31 #361906 - handling additional extensions + String addExts = req.getParameter("addExts"); + + if (addExts != null && !addExts.trim().equals("")) { + Vector<Extension> extsToBeAdded = new Vector<Extension>(); + + byte[] b = Utils.base64decode(addExts); + + // this b can be "Extension" Or "SEQUENCE OF Extension" + try { + DerValue b_der = new DerValue(b); + + while (b_der.data.available() != 0) { + Extension de = new Extension(b_der.data.getDerValue()); + + extsToBeAdded.addElement(de); + } + } catch (IOException e) { + // it could be a single extension + Extension de = new Extension(new DerValue(b)); + + extsToBeAdded.addElement(de); + } + if (extsToBeAdded.size() > 0) { + if (extensions == null) { + extensions = new CertificateExtensions(); + certInfo[i].set(X509CertInfo.EXTENSIONS, extensions); + } + for (int j = 0; j < extsToBeAdded.size(); j++) { + Extension theExt = (Extension) extsToBeAdded.elementAt(j); + + extensions.set(theExt.getExtensionId().toString(), theExt); + } + } + } + + if (extensions != null) { + try { + NSCertTypeExtension nsExtensions = + (NSCertTypeExtension) + extensions.get( + NSCertTypeExtension.NAME); + + if (nsExtensions != null) { + updateNSExtension(req, nsExtensions); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_PROCESS_NETSCAPE_EXTENSION", e.toString())); + } + + String pathLength = req.getParameter("pathLenConstraint"); + + if (pathLength != null) { + try { + int pathLen = Integer.parseInt(pathLength); + BasicConstraintsExtension bcExt = + (BasicConstraintsExtension) + extensions.get( + BasicConstraintsExtension.NAME); + + if (bcExt != null) { + Integer bcPathLen = (Integer) bcExt.get(BasicConstraintsExtension.PATH_LEN); + Boolean isCA = (Boolean) bcExt.get(BasicConstraintsExtension.IS_CA); + + if (bcPathLen != null && + bcPathLen.intValue() != pathLen && + isCA != null) { + BasicConstraintsExtension bcExt0 = + new BasicConstraintsExtension(isCA.booleanValue(), pathLen); + + extensions.delete(BasicConstraintsExtension.NAME); + extensions.set(BasicConstraintsExtension.NAME, + (Extension) bcExt0); + alterationCounter++; + } + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_PROCESS_CONSTRAINTS_EXTENSION", + e.toString())); + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_PROCESS_CONSTRAINTS_EXTENSION", + e.toString())); + } + } + + // handle Presence Server Extension + String PSE_Enable = req.getParameter("PSE_Enable"); + + if (PSE_Enable != null) { + boolean Critical = (req.getParameter("PSE_Critical") != null); + int Version = 0; + + try { + Version = Integer.parseInt(req.getParameter("PSE_Version")); + } catch (Exception e1) { + } + String StreetAddress = req.getParameter("PSE_StreetAddress"); + + if (StreetAddress == null) { + StreetAddress = ""; + } + String TelephoneNumber = req.getParameter("PSE_TelephoneNumber"); + + if (TelephoneNumber == null) { + TelephoneNumber = ""; + } + String RFC822Name = req.getParameter("PSE_RFC822Name"); + + if (RFC822Name == null) { + RFC822Name = ""; + } + String IMID = req.getParameter("PSE_IMID"); + + if (IMID == null) { + IMID = ""; + } + String HostName = req.getParameter("PSE_HostName"); + + if (HostName == null) { + HostName = ""; + } + int PortNumber = 0; + + try { + PortNumber = Integer.parseInt(req.getParameter("PSE_PortNumber")); + } catch (Exception e1) { + } + int MaxUsers = 0; + + try { + MaxUsers = Integer.parseInt(req.getParameter("PSE_MaxUsers")); + } catch (Exception e1) { + } + int ServiceLevel = 0; + + try { + ServiceLevel = Integer.parseInt(req.getParameter("PSE_ServiceLevel")); + } catch (Exception e1) { + } + // create extension + PresenceServerExtension pseExt = + new PresenceServerExtension(Critical, Version, StreetAddress, + TelephoneNumber, RFC822Name, IMID, HostName, PortNumber, MaxUsers, + ServiceLevel); + + extensions.set(pseExt.getExtensionId().toString(), pseExt); + } + + if (mExtraAgentParams) { + @SuppressWarnings("unchecked") + Enumeration<String> extraparams = req.getParameterNames(); + int l = IRequest.AGENT_PARAMS.length() + 1; + int ap_counter = 0; + Hashtable<String, String> agentparamsargblock = new Hashtable<String, String>(); + + if (extraparams != null) { + while (extraparams.hasMoreElements()) { + String s = extraparams.nextElement(); + + if (s.startsWith(IRequest.AGENT_PARAMS)) { + String param_value = req.getParameter(s); + + if (param_value != null) { + String new_name = s.substring(l); + + agentparamsargblock.put(new_name, param_value); + ap_counter += 1; + } + } + } + } + if (ap_counter > 0) { + r.setExtData(IRequest.AGENT_PARAMS, agentparamsargblock); + alterationCounter++; + } + } + + // this set() trigger this rebuild of internal + // raw der encoding cache of X509CertInfo. + // Otherwise, the above change wont have effect. + certInfo[i].set(X509CertInfo.EXTENSIONS, extensions); + } + alterationCounter += updateExtensionsInRequest(req, r); + } + if (alterationCounter > 0) { + mQueue.updateRequest(r); + } + } + + mQueue.approveRequest(r); + + if (r.getRequestStatus().equals(RequestStatus.PENDING)) { + cmsReq.setResult(r); + cmsReq.setStatus(CMSRequest.PENDING); + if (certInfo != null) { + for (int i = 0; i < certInfo.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "pending", + certInfo[i].get(X509CertInfo.SUBJECT), + "" } + ); + } + } else { + if (subject != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "pending", + subject, + "" } + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "pending" } + ); + } + } + } else if (r.getRequestStatus().equals( + RequestStatus.APPROVED) || + r.getRequestStatus().equals( + RequestStatus.SVC_PENDING)) { + cmsReq.setResult(r); + cmsReq.setStatus(CMSRequest.SVC_PENDING); + if (certInfo != null) { + for (int i = 0; i < certInfo.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + r.getRequestStatus(), + certInfo[i].get(X509CertInfo.SUBJECT), + "" } + ); + } + } else { + if (subject != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + r.getRequestStatus(), + subject, + "" } + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + r.getRequestStatus() } + ); + } + } + } else if (r.getRequestStatus().equals( + RequestStatus.COMPLETE)) { + cmsReq.setStatus(CMSRequest.SUCCESS); + + // XXX make the repeat record. + // Get the certificate(s) from the request + X509CertImpl issuedCerts[] = + r.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + // return potentially more than one certificates. + if (issuedCerts != null) { + long endTime = CMS.getCurrentDate().getTime(); + StringBuffer sbuf = new StringBuffer(); + + //header.addBigIntegerValue("serialNumber", + //issuedCerts[0].getSerialNumber(),16); + for (int i = 0; i < issuedCerts.length; i++) { + if (i != 0) + sbuf.append(", "); + sbuf.append("0x" + + issuedCerts[i].getSerialNumber().toString(16)); + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "completed", + issuedCerts[i].getSubjectDN(), + "cert issued serial number: 0x" + + + issuedCerts[i].getSerialNumber().toString(16) + " time: " + + (endTime - startTime) } + ); + + // store a message in the signed audit log file + // (one for each manual "agent" + // cert request processed - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditInfoName, + auditInfoCertValue(issuedCerts[i])); + + audit(auditMessage); + } + header.addStringValue( + "serialNumber", sbuf.toString()); + } else { + if (subject != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "completed", + subject, + "" } + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "completed" } + ); + } + + // store a message in the signed audit log file + // (manual "agent" cert request processed + // - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditInfoName, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + } + + // grant trusted manager or agent privileges + try { + int res = grant_privileges( + cmsReq, r, issuedCerts, header); + + if (res != 0) { + header.addStringValue(GRANT_ERROR, "SUCCESS"); + } + } catch (EBaseException e) { + header.addStringValue(GRANT_ERROR, e.toString()); + } + + // if this is a RA, show the certificate right away + // since ther is no cert database. + /* + if (mAuthority instanceof RegistrationAuthority) { + Object[] results = + new Object[] { issuedCerts, grantError }; + cmsReq.setResult(results); + renderTemplate(cmsReq, + mReqCompletedTemplate, REQ_COMPLETED_FILLER); + + return; + } + */ + + cmsReq.setResult(r); + + String scheme = req.getScheme(); + + if (scheme.equals("http") && + connectionIsSSL(req)) + scheme = "https"; + + /* + header.addStringValue( + "authorityid", mAuthority.getId()); + header.addStringValue("serviceURL", scheme +"://"+ + req.getServerName() + ":"+ + req.getServerPort() + + req.getRequestURI()); + */ + + if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) { + header.addStringValue("dirEnabled", "yes"); + + Integer[] ldapPublishStatus = + r.getExtDataInIntegerArray("ldapPublishStatus"); + int certsUpdated = 0; + + if (ldapPublishStatus != null) { + for (int i = 0; i < ldapPublishStatus.length; i++) { + if (ldapPublishStatus[i] == IRequest.RES_SUCCESS) { + certsUpdated++; + } + } + } + header.addIntegerValue("certsUpdated", certsUpdated); + + } else { + header.addStringValue("dirEnabled", "no"); + } + } + + } else if (toDo.equals("reject")) { + mQueue.rejectRequest(r); + if (certInfo != null) { + for (int i = 0; i < certInfo.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "rejected", + certInfo[i].get(X509CertInfo.SUBJECT), + "" } + ); + } + } else { + if (subject != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "rejected", + subject, + "" } + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "rejected" } + ); + } + } + + // store a message in the signed audit log file + // (manual "agent" cert request processed - "rejected") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_REJECTION_REASON[1]); + + audit(auditMessage); + + } else if (toDo.equals("cancel")) { + mQueue.cancelRequest(r); + + if (certInfo != null) { + for (int i = 0; i < certInfo.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "canceled", + certInfo[i].get(X509CertInfo.SUBJECT), + "" } + ); + } + } else { + if (subject != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "canceled", + subject, + "" } + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "canceled" } + ); + } + + } + + // store a message in the signed audit log file + // (manual "agent" cert request processed - "cancelled") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[1]); + + audit(auditMessage); + + } else if (toDo.equals("clone")) { + IRequest clonedRequest = mQueue.cloneAndMarkPending(r); + + header.addStringValue("clonedRequestId", + clonedRequest.getRequestId().toString()); + + if (certInfo != null) { + for (int i = 0; i < certInfo.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "cloned to reqID: " + + clonedRequest.getRequestId().toString(), + certInfo[i].get(X509CertInfo.SUBJECT), + "" } + ); + } + } else { + if (subject != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "cloned to reqID: " + + clonedRequest.getRequestId().toString(), + subject, + "" } + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "cloned to reqID: " + + clonedRequest.getRequestId().toString() } + ); + } + } + + // store a message in the signed audit log file + // ("agent" cert request for "cloning") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + } + } + + // add authority names to know what privileges can be requested. + if (CMS.getSubsystem("kra") != null) + header.addStringValue("localkra", "yes"); + if (CMS.getSubsystem("ca") != null) + header.addStringValue("localca", "yes"); + if (CMS.getSubsystem("ra") != null) + header.addStringValue("localra", "yes"); + + header.addBigIntegerValue("seqNum", seqNum, 10); + mParser.fillRequestIntoArg(locale, r, argSet, header); + String rid = r.getExtDataInString(IRequest.REMOTE_REQID); + + if (rid != null) + header.addStringValue("remoteReqID", rid); + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString())); + + // store a message in the signed audit log file + if (toDo != null) { + if (toDo.equals(SIGNED_AUDIT_CLONING)) { + // ("agent" cert request for "cloning") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) { + // (manual "agent" cert request processed - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) { + // (manual "agent" cert request processed - "cancelled") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[2]); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) { + // (manual "agent" cert request processed - "rejected") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_REJECTION_REASON[2]); + + audit(auditMessage); + } + } + + throw e; + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString())); + + // store a message in the signed audit log file + if (toDo != null) { + if (toDo.equals(SIGNED_AUDIT_CLONING)) { + // ("agent" cert request for "cloning") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) { + // (manual "agent" cert request processed - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) { + // (manual "agent" cert request processed - "cancelled") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[3]); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) { + // (manual "agent" cert request processed - "rejected") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_REJECTION_REASON[3]); + + audit(auditMessage); + } + } + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_ENCODING_ISSUED_CERT_ERROR")); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString())); + + // store a message in the signed audit log file + if (toDo != null) { + if (toDo.equals(SIGNED_AUDIT_CLONING)) { + // ("agent" cert request for "cloning") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) { + // (manual "agent" cert request processed - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) { + // (manual "agent" cert request processed - "cancelled") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[4]); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) { + // (manual "agent" cert request processed - "rejected") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_REJECTION_REASON[4]); + + audit(auditMessage); + } + } + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_ENCODING_ISSUED_CERT_ERROR")); + } catch (NoSuchAlgorithmException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString())); + + // store a message in the signed audit log file + if (toDo != null) { + if (toDo.equals(SIGNED_AUDIT_CLONING)) { + // ("agent" cert request for "cloning") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) { + // (manual "agent" cert request processed - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) { + // (manual "agent" cert request processed - "cancelled") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[5]); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) { + // (manual "agent" cert request processed - "rejected") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_REJECTION_REASON[5]); + + audit(auditMessage); + } + } + + throw new EBaseException(CMS.getUserMessage(locale, "CMS_BASE_INTERNAL_ERROR", e.toString())); + } + return; + } + + private void updateNSExtension(HttpServletRequest req, + NSCertTypeExtension ext) throws IOException { + try { + + if (req.getParameter("certTypeSSLServer") == null) { + ext.set(NSCertTypeExtension.SSL_SERVER, Boolean.valueOf(false)); + } else { + ext.set(NSCertTypeExtension.SSL_SERVER, Boolean.valueOf(true)); + } + + if (req.getParameter("certTypeSSLClient") == null) { + ext.set(NSCertTypeExtension.SSL_CLIENT, Boolean.valueOf(false)); + } else { + ext.set(NSCertTypeExtension.SSL_CLIENT, Boolean.valueOf(true)); + } + + if (req.getParameter("certTypeEmail") == null) { + ext.set(NSCertTypeExtension.EMAIL, Boolean.valueOf(false)); + } else { + ext.set(NSCertTypeExtension.EMAIL, Boolean.valueOf(true)); + } + + if (req.getParameter("certTypeObjSigning") == null) { + ext.set(NSCertTypeExtension.OBJECT_SIGNING, Boolean.valueOf(false)); + } else { + ext.set(NSCertTypeExtension.OBJECT_SIGNING, Boolean.valueOf(true)); + } + + if (req.getParameter("certTypeEmailCA") == null) { + ext.set(NSCertTypeExtension.EMAIL_CA, Boolean.valueOf(false)); + } else { + ext.set(NSCertTypeExtension.EMAIL_CA, Boolean.valueOf(true)); + } + + if (req.getParameter("certTypeSSLCA") == null) { + ext.set(NSCertTypeExtension.SSL_CA, Boolean.valueOf(false)); + } else { + ext.set(NSCertTypeExtension.SSL_CA, Boolean.valueOf(true)); + } + + if (req.getParameter("certTypeObjSigningCA") == null) { + ext.set(NSCertTypeExtension.OBJECT_SIGNING_CA, Boolean.valueOf(false)); + } else { + ext.set(NSCertTypeExtension.OBJECT_SIGNING_CA, Boolean.valueOf(true)); + } + } catch (CertificateException e) { + } + } + + /** + * This method sets extensions parameter into the request so + * that the NSCertTypeExtension policy creates new + * NSCertTypExtension with this setting. Note that this + * setting will not be used if the NSCertType Extension + * already exist in CertificateExtension. In that case, + * updateExtensions() will be called to set the extension + * parameter into the extension directly. + */ + private int updateExtensionsInRequest(HttpServletRequest req, IRequest r) { + int nChanges = 0; + + if (req.getParameter("certTypeSSLServer") != null) { + r.setExtData(NSCertTypeExtension.SSL_SERVER, "true"); + nChanges++; + } else { + r.deleteExtData(NSCertTypeExtension.SSL_SERVER); + nChanges++; + } + + if (req.getParameter("certTypeSSLClient") != null) { + r.setExtData(NSCertTypeExtension.SSL_CLIENT, "true"); + nChanges++; + } else { + r.deleteExtData(NSCertTypeExtension.SSL_CLIENT); + nChanges++; + } + + if (req.getParameter("certTypeEmail") != null) { + r.setExtData(NSCertTypeExtension.EMAIL, "true"); + nChanges++; + } else { + r.deleteExtData(NSCertTypeExtension.EMAIL); + nChanges++; + } + + if (req.getParameter("certTypeObjSigning") != null) { + r.setExtData(NSCertTypeExtension.OBJECT_SIGNING, "true"); + nChanges++; + } else { + r.deleteExtData(NSCertTypeExtension.OBJECT_SIGNING); + nChanges++; + } + + if (req.getParameter("certTypeEmailCA") != null) { + r.setExtData(NSCertTypeExtension.EMAIL_CA, "true"); + nChanges++; + } else { + r.deleteExtData(NSCertTypeExtension.EMAIL_CA); + nChanges++; + } + + if (req.getParameter("certTypeSSLCA") != null) { + r.setExtData(NSCertTypeExtension.SSL_CA, "true"); + nChanges++; + } else { + r.deleteExtData(NSCertTypeExtension.SSL_CA); + nChanges++; + } + + if (req.getParameter("certTypeObjSigningCA") != null) { + r.setExtData(NSCertTypeExtension.OBJECT_SIGNING_CA, "true"); + nChanges++; + } else { + r.deleteExtData(NSCertTypeExtension.OBJECT_SIGNING_CA); + nChanges++; + } + + return nChanges; + } + + protected static final String GRANT_ERROR = "grantError"; + + public static final String GRANT_TRUSTEDMGR_PRIVILEGE = "grantTrustedManagerPrivilege"; + public static final String GRANT_CMAGENT_PRIVILEGE = "grantCMAgentPrivilege"; + public static final String GRANT_RMAGENT_PRIVILEGE = "grantRMAgentPrivilege"; + public static final String GRANT_DRMAGENT_PRIVILEGE = "grantDRMAgentPrivilege"; + public static final String GRANT_UID = "grantUID"; + public static final String GRANT_PRIVILEGE = "grantPrivilege"; + + protected int grant_privileges( + CMSRequest cmsReq, IRequest req, Certificate[] certs, IArgBlock header) + throws EBaseException { + // get privileges to grant + IArgBlock httpParams = cmsReq.getHttpParams(); + + boolean grantTrustedMgr = + httpParams.getValueAsBoolean(GRANT_TRUSTEDMGR_PRIVILEGE, false); + boolean grantRMAgent = + httpParams.getValueAsBoolean(GRANT_RMAGENT_PRIVILEGE, false); + boolean grantCMAgent = + httpParams.getValueAsBoolean(GRANT_CMAGENT_PRIVILEGE, false); + boolean grantDRMAgent = + httpParams.getValueAsBoolean(GRANT_DRMAGENT_PRIVILEGE, false); + + if (!grantTrustedMgr && + !grantCMAgent && !grantRMAgent && !grantDRMAgent) { + return 0; + } else { + IAuthToken authToken = getAuthToken(req); + AuthzToken authzToken = null; + String resourceName = "certServer." + mAuthority.getId() + ".group"; + + try { + authzToken = authorize(mAclMethod, authToken, + resourceName, "add"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + String[] obj = new String[1]; + + if (grantTrustedMgr) + obj[0] = TRUSTED_RA_GROUP; + else if (grantRMAgent) + obj[0] = RA_AGENT_GROUP; + else if (grantCMAgent) + obj[0] = CA_AGENT_GROUP; + else if (grantDRMAgent) + obj[0] = KRA_AGENT_GROUP; + else + obj[0] = "unknown group"; + + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_UNAUTHORIZED_CREATE_GROUP", obj[0])); + } + } + + String uid = (String) httpParams.getValueAsString(GRANT_UID, null); + + if (uid == null || uid.length() == 0) { + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_MISSING_GRANT_UID")); + } + header.addStringValue(GRANT_UID, uid); + + String groupname = null, groupname1 = null; + String userType = ""; + + if (grantTrustedMgr) { + groupname = TRUSTED_RA_GROUP; + userType = Constants.PR_SUBSYSTEM_TYPE; + } else { + if (grantCMAgent) + groupname = CA_AGENT_GROUP; + else if (grantRMAgent) + groupname = RA_AGENT_GROUP; + + if (grantDRMAgent) { + if (groupname != null) + groupname1 = KRA_AGENT_GROUP; + else + groupname = KRA_AGENT_GROUP; + } + userType = Constants.PR_AGENT_TYPE; + } + + String privilege = + (groupname1 == null) ? groupname : groupname + " and " + groupname1; + + header.addStringValue(GRANT_PRIVILEGE, privilege); + + IUGSubsystem ug = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG); + IUser user = ug.createUser(uid); + + user.setFullName(uid); + user.setEmail(""); + user.setPhone(""); + user.setPassword(""); + user.setUserType(userType); + user.setState("1"); + IGroup group = ug.findGroup(groupname), group1 = null; + + if (group == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_FIND_GROUP_1", groupname)); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_FIND_GROUP_ERROR", groupname)); + } + if (groupname1 != null) { + group1 = ug.findGroup(groupname1); + if (group1 == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_FIND_GROUP_1", groupname)); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_FIND_GROUP_ERROR", groupname1)); + } + } + try { + ug.addUser(user); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_ADDING_USER_1", uid)); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_ADDING_USER_ERROR", uid)); + } + try { + if (certs[0] instanceof X509CertImpl) { + X509CertImpl tmp[] = (X509CertImpl[]) certs; + + user.setX509Certificates(tmp); + } + + ug.addUserCert(user); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_ADDING_CERT_1", uid)); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_ADDING_CERT_ERROR", uid)); + } + try { + group.addMemberName(uid); + ug.modifyGroup(group); + // for audit log + SessionContext sContext = SessionContext.getContext(); + String adminId = (String) sContext.get(SessionContext.USER_ID); + + mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP, + AuditFormat.LEVEL, AuditFormat.ADDUSERGROUPFORMAT, + new Object[] { adminId, uid, groupname } + ); + + if (group1 != null) { + group1.addMemberName(uid); + ug.modifyGroup(group1); + + mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP, + AuditFormat.LEVEL, AuditFormat.ADDUSERGROUPFORMAT, + new Object[] { adminId, uid, groupname1 } + ); + + } + } catch (Exception e) { + String msg = + "Could not add user " + uid + " to group " + groupname; + + if (group1 != null) + msg += " or group " + groupname1; + log(ILogger.LL_FAILURE, msg); + if (group1 == null) + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_ADDING_MEMBER", uid, groupname)); + else + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_ADDING_MEMBER_1", uid, groupname, groupname1)); + } + return 1; + } + + /** + * Signed Audit Log Info Name + * + * This method is called to obtain the "InfoName" for + * a signed audit log message. + * <P> + * + * @param type signed audit log request processing type + * @return id string containing the signed audit log message InfoName + */ + private String auditInfoName(String type) { + // in this case, do NOT strip preceding/trailing whitespace + // from passed-in String parameters (this is done below) + + String infoName = ILogger.UNIDENTIFIED; + + if (mSignedAuditLogger == null) { + return infoName; + } + + if (type != null) { + type = type.trim(); + + if (type.equals(SIGNED_AUDIT_ACCEPTANCE)) { + infoName = ILogger.SIGNED_AUDIT_ACCEPTANCE; + } else if (type.equals(SIGNED_AUDIT_CANCELLATION)) { + infoName = ILogger.SIGNED_AUDIT_CANCELLATION; + } else if (type.equals(SIGNED_AUDIT_REJECTION)) { + infoName = ILogger.SIGNED_AUDIT_REJECTION; + } + } + + return infoName; + } + + /** + * 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 + */ + private String auditInfoCertValue(X509CertImpl x509cert) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == 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 (base64Data.substring(i, i).getBytes() != EOL) { + sb.append(base64Data.substring(i, 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; + } + } +} + +class RAReqCompletedFiller extends ImportCertsTemplateFiller { + private static final String RA_AGENT_GROUP = "Registration Manager Agents"; + private static final String KRA_AGENT_GROUP = "Data Recovery Manager Agents"; + + public RAReqCompletedFiller() { + super(); + } + + public CMSTemplateParams getTemplateParams( + CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) + throws Exception { + + Object[] results = (Object[]) cmsReq.getResult(); + Object grantError = results[1]; + //X509CertImpl[] issuedCerts = (X509CertImpl[])results[0]; + Certificate[] issuedCerts = (Certificate[]) results[0]; + + cmsReq.setResult(issuedCerts); + CMSTemplateParams params = + super.getTemplateParams(cmsReq, authority, locale, e); + + if (grantError != null) { + IArgBlock header = params.getHeader(); + + if (grantError instanceof String) { + header.addStringValue( + ProcessCertReq.GRANT_ERROR, (String) grantError); + } else { + EBaseException ex = (EBaseException) grantError; + + header.addStringValue( + ProcessCertReq.GRANT_ERROR, ex.toString(locale)); + } + IArgBlock httpParams = cmsReq.getHttpParams(); + String uid = httpParams.getValueAsString( + ProcessCertReq.GRANT_UID, null); + + header.addStringValue(ProcessCertReq.GRANT_UID, uid); + boolean grantRMAgent = httpParams.getValueAsBoolean( + ProcessCertReq.GRANT_RMAGENT_PRIVILEGE, false); + boolean grantDRMAgent = httpParams.getValueAsBoolean( + ProcessCertReq.GRANT_DRMAGENT_PRIVILEGE, false); + String privilege = null; + + if (grantRMAgent) { + privilege = RA_AGENT_GROUP; + } + if (grantDRMAgent) { + if (privilege != null) + privilege += " and " + KRA_AGENT_GROUP; + else + privilege = KRA_AGENT_GROUP; + } + header.addStringValue(ProcessCertReq.GRANT_PRIVILEGE, privilege); + } + return params; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/ProcessReq.java b/base/common/src/com/netscape/cms/servlet/request/ProcessReq.java new file mode 100644 index 000000000..9c173d832 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/ProcessReq.java @@ -0,0 +1,334 @@ +// --- 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.request; + +import java.io.IOException; +import java.util.Locale; +import java.math.BigInteger; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Display Generic Request detail to the user. + * + * @version $Revision$, $Date$ + */ +public class ProcessReq extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -6941843162486565610L; + private final static String INFO = "processReq"; + private final static String SEQNUM = "seqNum"; + private final static String DO_ASSIGN = "doAssign"; + private final static String TPL_FILE = "processReq.template"; + private final static String OUT_ERROR = "errorDetails"; + private final static String PROP_PARSER = "parser"; + + private IRequestQueue mQueue = null; + private String mFormPath = null; + private IReqParser mParser = null; + private String[] mSigningAlgorithms = null; + + private static String[] DEF_SIGNING_ALGORITHMS = new String[] + { "SHA1withRSA", "SHA256withRSA", "SHA512withRSA", "SHA1withDSA", "MD5withRSA", "MD2withRSA" }; + + /** + * Process request. + */ + public ProcessReq() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "processReq.template" to process the response. + * The initialization parameter 'parser' is read from the + * servlet configration, and is used to set the type of request. + * The value of this parameter can be: + * <UL> + * <LI><B>CertReqParser.NODETAIL_PARSER</B> - Show certificate Summary + * <LI><B>CertReqParser.DETAIL_PARSER</B> - Show certificate detail + * <LI><B>KeyReqParser.PARSER</B> - Show key archival detail + * </UL> + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mQueue = mAuthority.getRequestQueue(); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + String tmp = sc.getInitParameter(PROP_PARSER); + + if (tmp != null) { + if (tmp.trim().equals("CertReqParser.NODETAIL_PARSER")) + mParser = CertReqParser.NODETAIL_PARSER; + else if (tmp.trim().equals("CertReqParser.DETAIL_PARSER")) + mParser = CertReqParser.DETAIL_PARSER; + else if (tmp.trim().equals("KeyReqParser.PARSER")) + mParser = KeyReqParser.PARSER; + } + + // override success and error templates to null - + // handle templates locally. + mTemplates.remove(CMSRequest.SUCCESS); + mTemplates.remove(CMSRequest.ERROR); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param seqNum + * <li>http.param doAssign reassign request. Value can be reassignToMe reassignToNobody + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + BigInteger seqNum = BigInteger.ONE.negate(); + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + String doAssign = null; + EBaseException error = null; + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + "Error getting template " + mFormPath + " Error " + e); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + try { + if (req.getParameter(SEQNUM) != null) { + seqNum = new BigInteger(req.getParameter(SEQNUM)); + } + doAssign = req.getParameter(DO_ASSIGN); + + if (seqNum.compareTo(BigInteger.ONE.negate()) > 0) { + // start authorization + AuthzToken authzToken = null; + + try { + if (doAssign == null) { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "read"); + } else if (doAssign.equals("toMe") || + doAssign.equals("reassignToMe")) { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "assign"); + } else if (doAssign.equals("reassignToNobody")) { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "unassign"); + } + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + process(argSet, header, seqNum, req, resp, + doAssign, locale[0]); + } else { + log(ILogger.LL_FAILURE, "Invalid sequence number " + seqNum); + error = new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_REQUEST_ID", + String.valueOf(seqNum))); + } + } catch (EBaseException e) { + error = e; + } catch (NumberFormatException e) { + error = new EBaseException(CMS.getUserMessage(locale[0], "CMS_BASE_INVALID_NUMBER_FORMAT")); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setError(error); + cmsReq.setStatus(CMSRequest.ERROR); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + "Error getting servlet output stream for rendering template. " + + "Error " + e); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + return; + } + + /** + * Sends request information to the calller. + * returns whether there was an error or not. + */ + private void process(CMSTemplateParams argSet, IArgBlock header, + BigInteger seqNum, HttpServletRequest req, + HttpServletResponse resp, + String doAssign, Locale locale) + throws EBaseException { + + header.addBigIntegerValue("seqNum", seqNum, 10); + + IRequest r = mQueue.findRequest(new RequestId(seqNum)); + + if (r != null) { + if (doAssign != null) { + if ((doAssign.equals("toMe")) + || (doAssign.equals("reassignToMe"))) { + SessionContext ctx = SessionContext.getContext(); + String id = (String) ctx.get(SessionContext.USER_ID); + + r.setRequestOwner(id); + mQueue.updateRequest(r); + } else if (doAssign.equals("reassignToNobody")) { + r.setRequestOwner(null); + mQueue.updateRequest(r); + } + } + + // add authority names to know what privileges can be requested. + if (CMS.getSubsystem("kra") != null) + header.addStringValue("localkra", "yes"); + if (CMS.getSubsystem("ca") != null) + header.addStringValue("localca", "yes"); + if (CMS.getSubsystem("ra") != null) + header.addStringValue("localra", "yes"); + + // DONT NEED TO DO THIS FOR DRM + if (mAuthority instanceof ICertAuthority) { + // Check/set signing algorithms dynamically. + // In RA mSigningAlgorithms could be null at startup if CA is not + // up and set later when CA comes back up. + // Once it's set assumed that it won't change. + String[] allAlgorithms = mSigningAlgorithms; + + if (allAlgorithms == null) { + allAlgorithms = mSigningAlgorithms = + ((ICertAuthority) mAuthority).getCASigningAlgorithms(); + if (allAlgorithms == null) { + CMS.debug( + "ProcessReq: signing algorithms set to All algorithms"); + allAlgorithms = AlgorithmId.ALL_SIGNING_ALGORITHMS; + } else + CMS.debug( + "ProcessReq: First signing algorithms is " + allAlgorithms[0]); + } + String validAlgorithms = null; + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < allAlgorithms.length; i++) { + if (i > 0) { + sb.append("+"); + sb.append(allAlgorithms[i]); + } else { + sb.append(allAlgorithms[i]); + } + } + validAlgorithms = sb.toString(); + if (validAlgorithms != null) + header.addStringValue("validAlgorithms", validAlgorithms); + if (mAuthority instanceof ICertificateAuthority) { + String signingAlgorithm = ((ICertificateAuthority) mAuthority).getDefaultAlgorithm(); + + if (signingAlgorithm != null) + header.addStringValue("caSigningAlgorithm", signingAlgorithm); + header.addLongValue("defaultValidityLength", + ((ICertificateAuthority) mAuthority).getDefaultValidity() / 1000); + } else if (mAuthority instanceof IRegistrationAuthority) { + header.addLongValue("defaultValidityLength", + ((IRegistrationAuthority) mAuthority).getDefaultValidity() / 1000); + } + X509CertImpl caCert = ((ICertAuthority) mAuthority).getCACert(); + + if (caCert != null) { + int caPathLen = caCert.getBasicConstraints(); + + header.addIntegerValue("caPathLen", caPathLen); + } + } + + mParser.fillRequestIntoArg(locale, r, argSet, header); + } else { + log(ILogger.LL_FAILURE, "Invalid sequence number " + seqNum.toString()); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_REQUEST_ID", + seqNum.toString())); + } + + return; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/QueryReq.java b/base/common/src/com/netscape/cms/servlet/request/QueryReq.java new file mode 100644 index 000000000..f6ae634f4 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/QueryReq.java @@ -0,0 +1,558 @@ +// --- 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.request; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; +import java.math.BigInteger; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.IRequestVirtualList; +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Show paged list of requests matching search criteria + * + * @version $Revision$, $Date$ + */ +public class QueryReq extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -8729364426329835378L; + // constants + private final static String INFO = "QueryReq"; + private final static String IN_SHOW_ALL = "showAll"; + private final static String IN_SHOW_WAITING = "showWaiting"; + private final static String IN_SHOW_IN_SERVICE = "showInService"; + private final static String IN_SHOW_PENDING = "showPending"; + private final static String IN_SHOW_CANCELLED = "showCancelled"; + private final static String IN_SHOW_REJECTED = "showRejected"; + private final static String IN_SHOW_COMPLETED = "showCompleted"; + private final static String IN_MAXCOUNT = "maxCount"; + private final static String IN_TOTALCOUNT = "totalRecordCount"; + private final static String ON = "on"; + private final static String PROP_PARSER = "parser"; + + private final static String TPL_FILE = "queryReq.template"; + + private final static String OUT_SERVICE_URL = "serviceURL"; + private final static String OUT_OP = "op"; + private final static String OUT_MAXCOUNT = IN_MAXCOUNT; + private final static String OUT_TOTALCOUNT = IN_TOTALCOUNT; + private final static String OUT_CURRENTCOUNT = "currentRecordCount"; + private final static String OUT_SENTINEL_DOWN = "querySentinelDown"; + private final static String OUT_SHOW_COMPLETED = IN_SHOW_COMPLETED; + private final static String OUT_SEQNUM = "seqNum"; + private final static String OUT_STATUS = "status"; + private final static String OUT_CREATE_ON = "createdOn"; + private final static String OUT_UPDATE_ON = "updatedOn"; + private final static String OUT_UPDATE_BY = "updatedBy"; + private final static String OUT_REQUESTING_USER = "requestingUser"; + //keeps track of where to begin if page down + private final static String OUT_FIRST_ENTRY_ON_PAGE = "firstEntryOnPage"; + //keeps track of where to begin if page up + private final static String OUT_LAST_ENTRY_ON_PAGE = "lastEntryOnPage"; + private final static String OUT_SUBJECT = "subject"; + private final static String OUT_REQUEST_TYPE = "requestType"; + private final static String OUT_COMMENTS = "requestorComments"; + private final static String OUT_SERIALNO = "serialNumber"; + private final static String OUT_OWNER_NAME = "ownerName"; + private final static String OUT_PUBLIC_KEY_INFO = + "subjectPublicKeyInfo"; + private final static String OUT_ERROR = "error"; + private final static String OUT_AUTHORITY_ID = "authorityid"; + + // variables + private IReqParser mParser = null; + private IRequestQueue mQueue = null; + private String mFormPath = null; + private int mMaxReturns = 2000; + + public CMSRequest newCMSRequest() { + return new CMSRequest(); + } + + /** + * Constructor + */ + public QueryReq() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "queryReq.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mQueue = mAuthority.getRequestQueue(); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + try { + mMaxReturns = Integer.parseInt(sc.getInitParameter("maxResults")); + } catch (Exception e) { + /* do nothing, just use the default if integer parsing failed */ + } + + String tmp = sc.getInitParameter(PROP_PARSER); + + if (tmp != null) { + if (tmp.trim().equals("CertReqParser.NODETAIL_PARSER")) + mParser = CertReqParser.NODETAIL_PARSER; + else if (tmp.trim().equals("CertReqParser.DETAIL_PARSER")) + mParser = CertReqParser.DETAIL_PARSER; + else if (tmp.trim().equals("KeyReqParser.PARSER")) + mParser = KeyReqParser.PARSER; + } + + // override success and error templates to null - + // handle templates locally. + mTemplates.remove(CMSRequest.SUCCESS); + mTemplates.remove(CMSRequest.ERROR); + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + private String getRequestType(String p) { + String filter = "(requestType=*)"; + + if (p == null) + return filter; + if (p.equals(IRequest.ENROLLMENT_REQUEST)) { + filter = "(requestType=" + IRequest.ENROLLMENT_REQUEST + ")"; + } else if (p.equals(IRequest.RENEWAL_REQUEST)) { + filter = "(requestType=" + IRequest.RENEWAL_REQUEST + ")"; + } else if (p.equals(IRequest.REVOCATION_REQUEST)) { + filter = "(requestType=" + IRequest.REVOCATION_REQUEST + ")"; + } else if (p.equals(IRequest.UNREVOCATION_REQUEST)) { + filter = "(requestType=" + IRequest.UNREVOCATION_REQUEST + ")"; + } else if (p.equals(IRequest.KEYARCHIVAL_REQUEST)) { + filter = "(requestType=" + IRequest.KEYARCHIVAL_REQUEST + ")"; + } else if (p.equals(IRequest.KEYRECOVERY_REQUEST)) { + filter = "(requestType=" + IRequest.KEYRECOVERY_REQUEST + ")"; + } else if (p.equals(IRequest.GETCACHAIN_REQUEST)) { + filter = "(requestType=" + IRequest.GETCACHAIN_REQUEST + ")"; + } else if (p.equals(IRequest.GETREVOCATIONINFO_REQUEST)) { + filter = "(requestType=" + IRequest.GETREVOCATIONINFO_REQUEST + ")"; + } else if (p.equals(IRequest.GETCRL_REQUEST)) { + filter = "(requestType=" + IRequest.GETCRL_REQUEST + ")"; + } else if (p.equals(IRequest.GETCERTS_REQUEST)) { + filter = "(requestType=" + IRequest.GETCERTS_REQUEST + ")"; + } else if (p.equals(IRequest.NETKEY_KEYGEN_REQUEST)) { + filter = "(requestType=" + IRequest.NETKEY_KEYGEN_REQUEST + ")"; + } else if (p.equals(IN_SHOW_ALL)) { + filter = "(requestType=*)"; + } + return filter; + } + + private String getRequestState(String p) { + String filter = "(requeststate=*)"; + + if (p == null) + return filter; + if (p.equals(IN_SHOW_WAITING)) { + filter = "(requeststate=pending)"; + } else if (p.equals(IN_SHOW_IN_SERVICE)) { + filter = "(requeststate=svc_pending)"; + } else if (p.equals(IN_SHOW_PENDING)) { + filter = "(requeststate=pending)"; + } else if (p.equals(IN_SHOW_CANCELLED)) { + filter = "(requeststate=canceled)"; + } else if (p.equals(IN_SHOW_REJECTED)) { + filter = "(requeststate=rejected)"; + } else if (p.equals(IN_SHOW_COMPLETED)) { + filter = "(requeststate=complete)"; + } else if (p.equals(IN_SHOW_ALL)) { + filter = "(requeststate=*)"; + } + return filter; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param reqState request state (one of showAll, showWaiting, showInService, showCancelled, showRejected, + * showCompleted) + * <li>http.param reqType + * <li>http.param seqNumFromDown request ID to start at (decimal, or hex if when paging down seqNumFromDown starts + * with 0x) + * <li>http.param seqNumFromUp request ID to start at (decimal, or hex if when paging up seqNumFromUp starts with + * 0x) + * <li>http.param maxCount maximum number of records to show + * <li>http.param totalCount total number of records in set of pages + * <li>http.param direction "up", "down", "begin", or "end" + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + + public void process(CMSRequest cmsReq) throws EBaseException { + CMS.debug("in QueryReq servlet"); + + // Authentication / Authorization + + HttpServletRequest req = cmsReq.getHttpReq(); + IAuthToken authToken = authenticate(cmsReq); + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "list"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + // if get a EBaseException we just throw it. + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + /** + * WARNING: + * + * PLEASE DO NOT TOUCH THE FILTER HERE. ALL FILTERS ARE INDEXED. + * + **/ + String filter = null; + String reqState = req.getParameter("reqState"); + String reqType = req.getParameter("reqType"); + + if (reqState == null || reqType == null) { + filter = "(requeststate=*)"; + } else if (reqState.equals(IN_SHOW_ALL) && + reqType.equals(IN_SHOW_ALL)) { + filter = "(requeststate=*)"; + } else if (reqState.equals(IN_SHOW_ALL)) { + filter = getRequestType(reqType); + } else if (reqType.equals(IN_SHOW_ALL)) { + filter = getRequestState(reqState); + } else { + filter = "(&" + getRequestState(reqState) + + getRequestType(reqType) + ")"; + } + + String direction = "begin"; + if (req.getParameter("direction") != null) { + direction = req.getParameter("direction").trim(); + } + + BigInteger top = BigInteger.ZERO; + BigInteger bottom = BigInteger.ZERO; + + try { + String top_s = req.getParameter(OUT_FIRST_ENTRY_ON_PAGE); + if (top_s == null) + top_s = "0"; + + String bottom_s = req.getParameter(OUT_LAST_ENTRY_ON_PAGE); + if (bottom_s == null) + bottom_s = "0"; + + if (top_s.trim().startsWith("0x")) { + top = new BigInteger(top_s.trim().substring(2), 16); + } else { + top = new BigInteger(top_s.trim()); + } + if (bottom_s.trim().startsWith("0x")) { + bottom = new BigInteger(bottom_s.trim().substring(2), 16); + } else { + bottom = new BigInteger(bottom_s.trim()); + } + + } catch (NumberFormatException e) { + + } + + // avoid NumberFormatException to the user interface + int maxCount = 10; + try { + maxCount = Integer.parseInt(req.getParameter(IN_MAXCOUNT)); + } catch (Exception e) { + } + if (maxCount > mMaxReturns) { + CMS.debug("Resetting page size from " + maxCount + " to " + mMaxReturns); + maxCount = mMaxReturns; + } + + HttpServletResponse resp = cmsReq.getHttpResp(); + CMSTemplateParams argset = doSearch(locale[0], filter, maxCount, direction, top, bottom); + + argset.getFixed().addStringValue("reqType", reqType); + argset.getFixed().addStringValue("reqState", reqState); + argset.getFixed().addIntegerValue("maxCount", maxCount); + + try { + form.getOutput(argset); + resp.setContentType("text/html"); + form.renderOutput(resp.getOutputStream(), argset); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + + /** + * Perform search based on direction button pressed + * + * @param filter ldap filter indicating which VLV to search through. This can be + * 'all requests', 'pending', etc + * @param count the number of requests to show per page + * @param direction either 'begin', 'end', 'previous' or 'next' (defaults to end) + * @param top the number of the request shown on at the top of the current page + * @param bottom the number of the request shown on at the bottom of the current page + * @return + */ + + private CMSTemplateParams doSearch(Locale l, String filter, + int count, String direction, BigInteger top, BigInteger bottom) { + CMSTemplateParams ctp = null; + if (direction.equals("previous")) { + ctp = doSearch(l, filter, -count, top); + } else if (direction.equals("next")) { + bottom = bottom.add(BigInteger.ONE); + ctp = doSearch(l, filter, count, bottom); + } else if (direction.equals("begin")) { + ctp = doSearch(l, filter, count, BigInteger.ZERO); + } else if (direction.equals("first")) { + ctp = doSearch(l, filter, count, bottom); + } else { // if 'direction is 'end', default here + ctp = doSearch(l, filter, -count, BigInteger.ONE.negate()); + } + return ctp; + } + + /** + * + * @param locale + * @param filter the types of requests to return - this must match the VLV index + * @param count maximum number of records to return + * @param marker indication of the request ID where the page is anchored + * @return + */ + + private CMSTemplateParams doSearch( + Locale locale, + String filter, + int count, + BigInteger marker) { + + IArgBlock header = CMS.createArgBlock(); + IArgBlock context = CMS.createArgBlock(); + CMSTemplateParams argset = new CMSTemplateParams(header, context); + + try { + long startTime = CMS.getCurrentDate().getTime(); + // preserve the type of request that we are + // requesting. + + header.addStringValue(OUT_AUTHORITY_ID, mAuthority.getId()); + header.addStringValue(OUT_REQUESTING_USER, "admin"); + + boolean jumptoend = false; + if (marker.toString().equals("-1")) { + marker = BigInteger.ZERO; // I think this is inconsequential + jumptoend = true; // override to '99' during search + } + + RequestId id = new RequestId(marker); + IRequestVirtualList list = mQueue.getPagedRequestsByFilter( + id, + jumptoend, + filter, + ((count < 0) ? count - 1 : count + 1), + "requestId"); + + int maxCount = 0; + if (count < 0 && jumptoend) { + maxCount = -count; + } else if (count < 0) { + maxCount = -count + 1; + } else { + maxCount = count; + } + int totalCount = (jumptoend) ? maxCount : + (list.getSize() - list.getCurrentIndex()); + header.addIntegerValue(OUT_TOTALCOUNT, totalCount); + header.addIntegerValue(OUT_CURRENTCOUNT, list.getSize()); + + Vector<IRequest> v = fetchRecords(list, maxCount); + v = normalizeOrder(v); + trim(v, id); + + int currentCount = 0; + BigInteger curNum = BigInteger.ZERO; + BigInteger firstNum = BigInteger.ONE.negate(); + Enumeration<IRequest> requests = v.elements(); + + while (requests.hasMoreElements()) { + IRequest request = null; + try { + request = requests.nextElement(); + } catch (Exception e) { + CMS.debug("Error displaying request:" + e.getMessage()); + // handled below + } + if (request == null) { + log(ILogger.LL_WARN, "Error display request on page"); + continue; + } + + curNum = new BigInteger(request.getRequestId().toString()); + + if (firstNum.equals(BigInteger.ONE.negate())) { + firstNum = curNum; + } + + IArgBlock rec = CMS.createArgBlock(); + mParser.fillRequestIntoArg(locale, request, argset, rec); + mQueue.releaseRequest(request); + argset.addRepeatRecord(rec); + + currentCount++; + + }// while + long endTime = CMS.getCurrentDate().getTime(); + + header.addIntegerValue(OUT_CURRENTCOUNT, currentCount); + header.addStringValue("time", Long.toString(endTime - startTime)); + header.addBigIntegerValue(OUT_FIRST_ENTRY_ON_PAGE, firstNum, 10); + header.addBigIntegerValue(OUT_LAST_ENTRY_ON_PAGE, curNum, 10); + + } catch (EBaseException e) { + header.addStringValue(OUT_ERROR, e.toString(locale)); + } catch (Exception e) { + } + return argset; + } + + /** + * If the vector contains the marker element at the end, remove it. + * + * @param v The vector to trim + * @param marker the marker to look for. + */ + private void trim(Vector<IRequest> v, RequestId marker) { + int i = v.size() - 1; + if (v.elementAt(i).getRequestId().toString().equals( + marker.toString())) { + v.remove(i); + } + } + + /** + * Sometimes the list comes back from LDAP in reverse order. This function makes + * sure the results are in 'forward' order. + * + * @param list + * @return + */ + private Vector<IRequest> fetchRecords(IRequestVirtualList list, int maxCount) { + + Vector<IRequest> v = new Vector<IRequest>(); + int count = list.getSize(); + int c = 0; + for (int i = 0; i < count; i++) { + IRequest request = list.getElementAt(i); + if (request != null) { + v.add(request); + c++; + } + if (c >= maxCount) + break; + } + + return v; + + } + + /** + * If the requests are in backwards order, reverse the list + * + * @param list + * @return + */ + private Vector<IRequest> normalizeOrder(Vector<IRequest> list) { + + BigInteger firstrequestnum = new BigInteger(list.elementAt(0) + .getRequestId().toString()); + BigInteger lastrequestnum = new BigInteger(list.elementAt(list + .size() - 1).getRequestId().toString()); + boolean reverse = false; + if (firstrequestnum.compareTo(lastrequestnum) > 0) { + reverse = true; // if the order is backwards, place items at the beginning + } + Vector<IRequest> v = new Vector<IRequest>(); + int count = list.size(); + for (int i = 0; i < count; i++) { + IRequest request = list.elementAt(i); + if (request != null) { + if (reverse) + v.add(0, request); + else + v.add(request); + } + } + + return v; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/ReqParser.java b/base/common/src/com/netscape/cms/servlet/request/ReqParser.java new file mode 100644 index 000000000..230ddb433 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/ReqParser.java @@ -0,0 +1,79 @@ +// --- 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.request; + +import java.util.Locale; +import java.math.BigInteger; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.common.CMSTemplateParams; + +/** + * A class representing a request parser. + * <P> + * + * @version $Revision$, $Date$ + */ +public class ReqParser implements IReqParser { + + private final static String TYPE = "requestType"; + private final static String STATUS = "status"; + private final static String CREATE_ON = "createdOn"; + private final static String UPDATE_ON = "updatedOn"; + private final static String UPDATE_BY = "updatedBy"; + + /** + * Constructs a request parser. + */ + public ReqParser() { + } + + /** + * Maps request object into argument block. + */ + public void fillRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg) + throws EBaseException { + arg.addStringValue(TYPE, req.getRequestType()); + arg.addBigIntegerValue("seqNum", + new BigInteger(req.getRequestId().toString()), 10); + arg.addStringValue(STATUS, + req.getRequestStatus().toString()); + arg.addLongValue(CREATE_ON, + req.getCreationTime().getTime() / 1000); + arg.addLongValue(UPDATE_ON, + req.getModificationTime().getTime() / 1000); + String updatedBy = req.getExtDataInString(IRequest.UPDATED_BY); + + if (updatedBy == null) + updatedBy = ""; + arg.addStringValue(UPDATE_BY, updatedBy); + + SessionContext ctx = SessionContext.getContext(); + String id = (String) ctx.get(SessionContext.USER_ID); + + arg.addStringValue("callerName", id); + + String owner = req.getRequestOwner(); + + if (owner != null) + arg.addStringValue("assignedTo", owner); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/SearchReqs.java b/base/common/src/com/netscape/cms/servlet/request/SearchReqs.java new file mode 100644 index 000000000..08d5805b6 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/SearchReqs.java @@ -0,0 +1,336 @@ +// --- 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.request; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Date; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestList; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Search for certificates matching complex query filter + * + * @version $Revision$, $Date$ + */ +public class SearchReqs extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 2449481964851735051L; + private final static String TPL_FILE = "queryReq.template"; + private final static String INFO = "QueryReq"; + private final static String PROP_MAX_SEARCH_RETURNS = "maxSearchReqReturns"; + private final static String PROP_PARSER = "parser"; + private final static String CURRENT_TIME = "currentTime"; + private final static BigInteger MINUS_ONE = new BigInteger("-1"); + private final static String OUT_AUTHORITY_ID = "authorityid"; + private final static String OUT_REQUESTING_USER = "requestingUser"; + private final static String OUT_SEQNUM_FROM = "seqNumFrom"; + private final static String OUT_MAXCOUNT = "maxCount"; + private final static String OUT_TOTALCOUNT = "totalRecordCount"; + private final static String OUT_CURRENTCOUNT = "currentRecordCount"; + private final static String OUT_SENTINEL = "querySentinel"; + private final static String OUT_ERROR = "error"; + private final static int MAX_RESULTS = 1000; + + private IRequestQueue mQueue = null; + private IReqParser mParser = null; + private String mFormPath = null; + private int mMaxReturns = MAX_RESULTS; + private int mTimeLimits = 30; /* in seconds */ + + /** + * Constructs query key servlet. + */ + public SearchReqs() { + super(); + } + + /** + * initialize the servlet. This servlet uses queryReq.template + * to render the response + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success to render own template. + mTemplates.remove(CMSRequest.SUCCESS); + + if (mAuthority instanceof ISubsystem) { + ISubsystem sub = (ISubsystem) mAuthority; + IConfigStore authConfig = sub.getConfigStore(); + + if (authConfig != null) { + try { + mMaxReturns = authConfig.getInteger(PROP_MAX_SEARCH_RETURNS, MAX_RESULTS); + } catch (EBaseException e) { + // do nothing + } + } + } + if (mAuthority instanceof ICertificateAuthority) { + ICertificateAuthority ca = (ICertificateAuthority) mAuthority; + mQueue = ca.getRequestQueue(); + } + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + /* Server-Side time limit */ + try { + int maxResults = Integer.parseInt(sc.getInitParameter("maxResults")); + if (maxResults < mMaxReturns) + mMaxReturns = maxResults; + } catch (Exception e) { + /* do nothing, just use the default if integer parsing failed */ + } + try { + mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits")); + } catch (Exception e) { + /* do nothing, just use the default if integer parsing failed */ + } + + String tmp = sc.getInitParameter(PROP_PARSER); + + if (tmp != null) { + if (tmp.trim().equals("CertReqParser.NODETAIL_PARSER")) + mParser = CertReqParser.NODETAIL_PARSER; + else if (tmp.trim().equals("CertReqParser.DETAIL_PARSER")) + mParser = CertReqParser.DETAIL_PARSER; + else if (tmp.trim().equals("KeyReqParser.PARSER")) + mParser = KeyReqParser.PARSER; + } + + // override success and error templates to null - + // handle templates locally. + mTemplates.remove(CMSRequest.SUCCESS); + mTemplates.remove(CMSRequest.ERROR); + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Serves HTTP request. This format of this request is as follows: + * queryCert? + * [maxCount=<number>] + * [queryFilter=<filter>] + * [revokeAll=<filter>] + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "list"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + EBaseException error = null; + int maxResults = -1; + int timeLimit = -1; + + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + try { + String maxResultsStr = req.getParameter("maxResults"); + + if (maxResultsStr != null && maxResultsStr.length() > 0) + maxResults = Integer.parseInt(maxResultsStr); + String timeLimitStr = req.getParameter("timeLimit"); + + if (timeLimitStr != null && timeLimitStr.length() > 0) + timeLimit = Integer.parseInt(timeLimitStr); + + process(argSet, header, req.getParameter("queryRequestFilter"), authToken, + maxResults, timeLimit, req, resp, locale[0]); + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT")); + error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT")); + } catch (EBaseException e) { + error = e; + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + cmsReq.setStatus(CMSRequest.SUCCESS); + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + /** + * Process the key search. + */ + private void process(CMSTemplateParams argSet, IArgBlock header, + String filter, IAuthToken token, + int maxResults, int timeLimit, + HttpServletRequest req, HttpServletResponse resp, + Locale locale) + throws EBaseException { + + try { + long startTime = CMS.getCurrentDate().getTime(); + + if (filter.indexOf(CURRENT_TIME, 0) > -1) { + filter = insertCurrentTime(filter); + } + + String owner = req.getParameter("owner"); + String requestowner_filter = ""; + String newfilter = ""; + if (owner.length() == 0) { + newfilter = filter; + } else { + if (owner.equals("self")) { + String self_uid = token.getInString(IAuthToken.USER_ID); + requestowner_filter = "(requestowner=" + self_uid + ")"; + } else { + String uid = req.getParameter("uid"); + requestowner_filter = "(requestowner=" + uid + ")"; + } + newfilter = "(&" + requestowner_filter + filter.substring(2); + } + // xxx the filter includes serial number range??? + if (maxResults == -1 || maxResults > mMaxReturns) { + CMS.debug("Resetting maximum of returned results from " + maxResults + " to " + mMaxReturns); + maxResults = mMaxReturns; + } + if (timeLimit == -1 || timeLimit > mTimeLimits) { + CMS.debug("Resetting timelimit from " + timeLimit + " to " + mTimeLimits); + timeLimit = mTimeLimits; + } + IRequestList list = (timeLimit > 0) ? + mQueue.listRequestsByFilter(newfilter, maxResults, timeLimit) : + mQueue.listRequestsByFilter(newfilter, maxResults); + + int count = 0; + + while (list != null && list.hasMoreElements()) { + IRequest request = (IRequest) list.nextRequestObject(); + + if (request != null) { + count++; + IArgBlock rarg = CMS.createArgBlock(); + mParser.fillRequestIntoArg(locale, request, argSet, rarg); + argSet.addRepeatRecord(rarg); + long endTime = CMS.getCurrentDate().getTime(); + + header.addIntegerValue(OUT_CURRENTCOUNT, count); + header.addStringValue("time", Long.toString(endTime - startTime)); + } + } + header.addIntegerValue(OUT_TOTALCOUNT, count); + } catch (EBaseException e) { + CMS.getLogMessage("CMSGW_ERROR_LISTCERTS", e.toString()); + throw e; + } + return; + } + + private String insertCurrentTime(String filter) { + Date now = null; + StringBuffer newFilter = new StringBuffer(); + int k = 0; + int i = filter.indexOf(CURRENT_TIME, k); + + while (i > -1) { + if (now == null) + now = new Date(); + newFilter.append(filter.substring(k, i)); + newFilter.append(now.getTime()); + k = i + CURRENT_TIME.length(); + i = filter.indexOf(CURRENT_TIME, k); + } + if (k > 0) { + newFilter.append(filter.substring(k, filter.length())); + } + return newFilter.toString(); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/model/ArchivalRequestData.java b/base/common/src/com/netscape/cms/servlet/request/model/ArchivalRequestData.java new file mode 100644 index 000000000..8a25c6684 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/ArchivalRequestData.java @@ -0,0 +1,123 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +/** + * + */ +package com.netscape.cms.servlet.request.model; + +import javax.ws.rs.core.MultivaluedMap; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; + +/** + * @author alee + * + */ +@XmlRootElement(name="SecurityDataArchivalRequest") +@XmlAccessorType(XmlAccessType.FIELD) +public class ArchivalRequestData { + + private static final String CLIENT_ID = "clientID"; + private static final String TRANS_WRAPPED_SESSION_KEY = "transWrappedSessionKey"; + private static final String DATA_TYPE = "dataType"; + private static final String WRAPPED_PRIVATE_DATA = "wrappedPrivateData"; + + @XmlElement + protected String clientId; + + @XmlElement + protected String transWrappedSessionKey; + + @XmlElement + protected String dataType; + + @XmlElement + protected String wrappedPrivateData; + + public ArchivalRequestData() { + // required for JAXB (defaults) + } + + public ArchivalRequestData(MultivaluedMap<String, String> form) { + clientId = form.getFirst(CLIENT_ID); + transWrappedSessionKey = form.getFirst(TRANS_WRAPPED_SESSION_KEY); + dataType = form.getFirst(DATA_TYPE); + wrappedPrivateData = form.getFirst(WRAPPED_PRIVATE_DATA); + } + + /** + * @return the clientId + */ + public String getClientId() { + return clientId; + } + + /** + * @param clientId the clientId to set + */ + public void setClientId(String clientId) { + this.clientId = clientId; + } + + /** + * @return the transWrappedSessionKey + */ + public String getTransWrappedSessionKey() { + return transWrappedSessionKey; + } + + /** + * @param transWrappedSessionKey the transWrappedSessionKey to set + */ + public void setTransWrappedSessionKey(String transWrappedSessionKey) { + this.transWrappedSessionKey = transWrappedSessionKey; + } + + /** + * @return the dataType + */ + public String getDataType() { + return dataType; + } + + /** + * @param dataType the dataType to set + */ + public void setDataType(String dataType) { + this.dataType = dataType; + } + + /** + * @return the wrappedPrivateData + */ + public String getWrappedPrivateData() { + return wrappedPrivateData; + } + + /** + * @param wrappedPrivateData the wrappedPrivateData to set + */ + public void setWrappedPrivateData(String wrappedPrivateData) { + this.wrappedPrivateData = wrappedPrivateData; + } + + +} diff --git a/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestDAO.java b/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestDAO.java new file mode 100644 index 000000000..d1f1a27bd --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestDAO.java @@ -0,0 +1,326 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.request.model; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; + +import javax.ws.rs.Path; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.dbs.keydb.KeyId; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestList; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.IRequestVirtualList; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.base.model.Link; +import com.netscape.cms.servlet.key.KeyResource; +import com.netscape.cms.servlet.key.model.KeyDAO; +import com.netscape.cms.servlet.key.model.KeyDataInfos; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.cms.servlet.request.KeyRequestResource; + +/** + * @author alee + * + */ +public class KeyRequestDAO { + private IRequestQueue queue; + private IKeyRecoveryAuthority kra; + + private static String REQUEST_ARCHIVE_OPTIONS = IEnrollProfile.REQUEST_ARCHIVE_OPTIONS; + + private String[] vlvFilters = { + "(requeststate=*)", "(requesttype=enrollment)", + "(requesttype=recovery)", "(requeststate=canceled)", + "(&(requeststate=canceled)(requesttype=enrollment))", + "(&(requeststate=canceled)(requesttype=recovery))", + "(requeststate=rejected)", + "(&(requeststate=rejected)(requesttype=enrollment))", + "(&(requeststate=rejected)(requesttype=recovery))", + "(requeststate=complete)", + "(&(requeststate=complete)(requesttype=enrollment))", + "(&(requeststate=complete)(requesttype=recovery))" + }; + + public static final String ATTR_SERIALNO = "serialNumber"; + + public KeyRequestDAO() { + kra = ( IKeyRecoveryAuthority ) CMS.getSubsystem( "kra" ); + queue = kra.getRequestQueue(); + } + + /** + * Finds list of requests matching the specified search filter. + * + * If the filter corresponds to a VLV search, then that search is executed and the pageSize + * and start parameters are used. Otherwise, the maxResults and maxTime parameters are + * used in the regularly indexed search. + * + * @param filter - ldap search filter + * @param start - start position for VLV search + * @param pageSize - page size for VLV search + * @param maxResults - max results to be returned in normal search + * @param maxTime - max time for normal search + * @param uriInfo - uri context of request + * @return collection of key request info + * @throws EBaseException + */ + public KeyRequestInfos listRequests(String filter, RequestId start, int pageSize, int maxResults, int maxTime, + UriInfo uriInfo) throws EBaseException { + List <KeyRequestInfo> list = new ArrayList<KeyRequestInfo>(); + List <Link> links = new ArrayList<Link>(); + int totalSize = 0; + int current = 0; + + if (isVLVSearch(filter)) { + IRequestVirtualList vlvlist = queue.getPagedRequestsByFilter(start, false, filter, + pageSize +1 , "requestId"); + totalSize = vlvlist.getSize(); + current = vlvlist.getCurrentIndex(); + + int numRecords = (totalSize > (current + pageSize)) ? pageSize : + totalSize - current; + + for (int i=0; i < numRecords; i++) { + IRequest request = vlvlist.getElementAt(i); + list.add(createKeyRequestInfo(request, uriInfo)); + } + } else { + // The non-vlv requests are indexed, but are not paginated. + // We should think about whether they should be, or if we need to + // limit the number of results returned. + IRequestList requests = queue.listRequestsByFilter(filter, maxResults, maxTime); + + if (requests == null) { + return null; + } + while (requests.hasMoreElements()) { + RequestId rid = requests.nextElement(); + IRequest request = queue.findRequest(rid); + if (request != null) { + list.add(createKeyRequestInfo(request, uriInfo)); + } + } + } + + // builder for vlv links + MultivaluedMap<String, String> params = uriInfo.getQueryParameters(); + UriBuilder builder = uriInfo.getAbsolutePathBuilder(); + if (params.containsKey("requestState")) { + builder.queryParam("requestState", params.getFirst("requestState")); + } + if (params.containsKey("requestType")) { + builder.queryParam("requestType", params.getFirst("requestType")); + } + builder.queryParam("start", "{start}"); + builder.queryParam("pageSize", "{pageSize}"); + + // next link + if (totalSize > current + pageSize) { + int next = current + pageSize + 1; + URI nextUri = builder.clone().build(next,pageSize); + Link nextLink = new Link("next", nextUri.toString(), "application/xml"); + links.add(nextLink); + } + + // previous link + if (current >0) { + int previous = current - pageSize; + URI previousUri = builder.clone().build(previous,pageSize); + Link previousLink = new Link("previous", previousUri.toString(), "application/xml"); + links.add(previousLink); + } + + KeyRequestInfos ret = new KeyRequestInfos(); + ret.setRequests(list); + ret.setLinks(links); + return ret; + } + + /** + * Gets info for a specific request + * @param id + * @return info for specific request + * @throws EBaseException + */ + public KeyRequestInfo getRequest(RequestId id, UriInfo uriInfo) throws EBaseException { + IRequest request = queue.findRequest(id); + if (request == null) { + return null; + } + KeyRequestInfo info = createKeyRequestInfo(request, uriInfo); + return info; + } + /** + * Submits an archival request and processes it. + * @param data + * @return info for the request submitted. + * @throws EBaseException + */ + public KeyRequestInfo submitRequest(ArchivalRequestData data, UriInfo uriInfo) throws EBaseException { + String clientId = data.getClientId(); + String wrappedSecurityData = data.getWrappedPrivateData(); + String dataType = data.getDataType(); + + boolean keyExists = doesKeyExist(clientId, "active", uriInfo); + + if (keyExists == true) { + throw new EBaseException("Can not archive already active existing key!"); + } + + IRequest request = queue.newRequest(IRequest.SECURITY_DATA_ENROLLMENT_REQUEST); + + request.setExtData(REQUEST_ARCHIVE_OPTIONS, wrappedSecurityData); + request.setExtData(IRequest.SECURITY_DATA_CLIENT_ID, clientId); + request.setExtData(IRequest.SECURITY_DATA_TYPE, dataType); + + queue.processRequest(request); + + queue.markAsServiced(request); + + return createKeyRequestInfo(request, uriInfo); + } + /** + * Submits a key recovery request. + * @param data + * @return info on the recovery request created + * @throws EBaseException + */ + public KeyRequestInfo submitRequest(RecoveryRequestData data, UriInfo uriInfo) throws EBaseException { + + // set data using request.setExtData(field, data) + + String wrappedSessionKeyStr = data.getTransWrappedSessionKey(); + String wrappedPassPhraseStr = data.getSessionWrappedPassphrase(); + String nonceDataStr = data.getNonceData(); + + IRequest request = queue.newRequest(IRequest.SECURITY_DATA_RECOVERY_REQUEST); + + KeyId keyId = data.getKeyId(); + + Hashtable<String, Object> requestParams; + requestParams = kra.createVolatileRequest(request.getRequestId()); + + if(requestParams == null) { + throw new EBaseException("Can not create Volatile params in submitRequest!"); + } + + CMS.debug("Create volatile params for recovery request. " + requestParams); + + if (wrappedPassPhraseStr != null) { + requestParams.put(IRequest.SECURITY_DATA_SESS_PASS_PHRASE, wrappedPassPhraseStr); + } + + if (wrappedSessionKeyStr != null) { + requestParams.put(IRequest.SECURITY_DATA_TRANS_SESS_KEY, wrappedSessionKeyStr); + } + + if (nonceDataStr != null) { + requestParams.put(IRequest.SECURITY_DATA_IV_STRING_IN, nonceDataStr); + } + + request.setExtData(ATTR_SERIALNO, keyId.toString()); + + queue.processRequest(request); + + return createKeyRequestInfo(request, uriInfo); + } + + public void approveRequest(RequestId id) throws EBaseException { + IRequest request = queue.findRequest(id); + request.setRequestStatus(RequestStatus.APPROVED); + queue.updateRequest(request); + } + + public void rejectRequest(RequestId id) throws EBaseException { + IRequest request = queue.findRequest(id); + request.setRequestStatus(RequestStatus.CANCELED); + queue.updateRequest(request); + } + + public void cancelRequest(RequestId id) throws EBaseException { + IRequest request = queue.findRequest(id); + request.setRequestStatus(RequestStatus.REJECTED); + queue.updateRequest(request); + } + + public KeyRequestInfo createKeyRequestInfo(IRequest request, UriInfo uriInfo) { + KeyRequestInfo ret = new KeyRequestInfo(); + + ret.setRequestType(request.getRequestType()); + ret.setRequestStatus(request.getRequestStatus().toString()); + + Path keyRequestPath = KeyRequestResource.class.getAnnotation(Path.class); + RequestId rid = request.getRequestId(); + + UriBuilder reqBuilder = uriInfo.getBaseUriBuilder(); + reqBuilder.path(keyRequestPath.value() + "/" + rid); + ret.setRequestURL(reqBuilder.build().toString()); + + Path keyPath = KeyResource.class.getAnnotation(Path.class); + String kid = request.getExtDataInString("keyrecord"); + + UriBuilder keyBuilder = uriInfo.getBaseUriBuilder(); + keyBuilder.path(keyPath.value() + "/" + kid); + ret.setKeyURL(keyBuilder.build().toString()); + + return ret; + } + + private boolean isVLVSearch(String filter) { + for (int i=0; i < vlvFilters.length; i++) { + if (vlvFilters[i].equalsIgnoreCase(filter)) { + return true; + } + } + return false; + } + + //We only care if the key exists or not + private boolean doesKeyExist(String clientId, String keyStatus, UriInfo uriInfo) { + boolean ret = false; + String state = "active"; + + KeyDAO keys = new KeyDAO(); + + KeyDataInfos existingKeys; + String filter = "(&(" + IRequest.SECURITY_DATA_CLIENT_ID + "=" + clientId + ")" + + "(" + IRequest.SECURITY_DATA_STATUS + "=" + state + "))"; + try { + existingKeys = keys.listKeys(filter, 1, 10, uriInfo); + + if(existingKeys != null && existingKeys.getKeyInfos().size() > 0) { + ret = true; + } + } catch (EBaseException e) { + ret= false; + } + + return ret; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestInfo.java b/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestInfo.java new file mode 100644 index 000000000..f07c302dd --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestInfo.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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package com.netscape.cms.servlet.request.model; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; + +import com.netscape.certsrv.dbs.keydb.KeyId; +import com.netscape.certsrv.request.RequestId; + +@XmlRootElement(name="SecurityDataRequestInfo") +@XmlAccessorType(XmlAccessType.FIELD) +public class KeyRequestInfo { + + @XmlElement + protected String requestType; + + @XmlElement + protected String requestStatus; + + @XmlElement + protected String requestURL; + + @XmlElement + protected String keyURL; + + public KeyRequestInfo(){ + // required to be here for JAXB (defaults) + } + + /** + * @return the requestType + */ + public String getRequestType() { + return requestType; + } + + /** + * @param requestType the requestType to set + */ + public void setRequestType(String requestType) { + this.requestType = requestType; + } + + /** + * @return the requestStatus + */ + public String getRequestStatus() { + return requestStatus; + } + + /** + * @param requestStatus the requestStatus to set + */ + public void setRequestStatus(String requestStatus) { + this.requestStatus = requestStatus; + } + + /** + * @return the requestURL + */ + public String getRequestURL() { + return requestURL; + } + + /** + * @return the request ID in the requestURL + */ + public RequestId getRequestId() { + String id = requestURL.substring(requestURL.lastIndexOf("/") + 1); + return new RequestId(id); + } + + /** + * @param requestURL the requestURL to set + */ + public void setRequestURL(String requestURL) { + this.requestURL = requestURL; + } + + /** + * @return the keyURL + */ + public String getKeyURL() { + return keyURL; + } + + /** + * @return the key ID in the keyURL + */ + public KeyId getKeyId() { + String id = keyURL.substring(keyURL.lastIndexOf("/") + 1); + return new KeyId(id); + } + + /** + * @param keyURL the keyURL to set + */ + public void setKeyURL(String keyURL) { + this.keyURL = keyURL; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestInfos.java b/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestInfos.java new file mode 100644 index 000000000..dc1b6a5e4 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestInfos.java @@ -0,0 +1,89 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.request.model; + +import java.util.Collection; +import java.util.List; + +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import com.netscape.cms.servlet.base.model.Link; + +@XmlRootElement(name = "SecurityDataRequestInfos") +public class KeyRequestInfos { + protected Collection<KeyRequestInfo> requests; + protected List<Link> links; + + /** + * @return the requests + */ + @XmlElementRef + public Collection<KeyRequestInfo> getRequests() { + return requests; + } + + /** + * @param requests the requests to set + */ + public void setRequests(Collection<KeyRequestInfo> requests) { + this.requests = requests; + } + + /** + * @return the links + */ + @XmlElementRef + public List<Link> getLinks() { + return links; + } + + /** + * @param links the links to set + */ + public void setLinks(List<Link> links) { + this.links = links; + } + + @XmlTransient + public String getNext() { + if (links == null) { + return null; + } + for (Link link : links) { + if ("next".equals(link.getRelationship())) { + return link.getHref(); + } + } + return null; + } + + @XmlTransient + public String getPrevious() { + if (links == null) { + return null; + } + for (Link link : links) { + if ("previous".equals(link.getRelationship())) { + return link.getHref(); + } + } + return null; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/model/RecoveryRequestData.java b/base/common/src/com/netscape/cms/servlet/request/model/RecoveryRequestData.java new file mode 100644 index 000000000..80ec6d127 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/RecoveryRequestData.java @@ -0,0 +1,155 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +/** + * + */ +package com.netscape.cms.servlet.request.model; + +import javax.ws.rs.core.MultivaluedMap; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +import com.netscape.certsrv.dbs.keydb.KeyId; +import com.netscape.certsrv.dbs.keydb.KeyIdAdapter; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestIdAdapter; + +/** + * @author alee + * + */ +@XmlRootElement(name="SecurityDataRecoveryRequest") +@XmlAccessorType(XmlAccessType.FIELD) +public class RecoveryRequestData { + + private static final String KEY_ID = "keyId"; + private static final String REQUEST_ID = "requestId"; + private static final String TRANS_WRAPPED_SESSION_KEY = "transWrappedSessionKey"; + private static final String SESSION_WRAPPED_PASSPHRASE = "sessionWrappedPassphrase"; + private static final String NONCE_DATA = "nonceData"; + + @XmlElement + @XmlJavaTypeAdapter(KeyIdAdapter.class) + protected KeyId keyId; + + @XmlElement + @XmlJavaTypeAdapter(RequestIdAdapter.class) + protected RequestId requestId; + + @XmlElement + protected String transWrappedSessionKey; + + @XmlElement + protected String sessionWrappedPassphrase; + + @XmlElement + protected String nonceData; + + public RecoveryRequestData() { + // required for JAXB (defaults) + } + + public RecoveryRequestData(MultivaluedMap<String, String> form) { + if (form.containsKey(KEY_ID)) { + keyId = new KeyId(form.getFirst(KEY_ID)); + } + if (form.containsKey(REQUEST_ID)) { + requestId = new RequestId(form.getFirst(REQUEST_ID)); + } + transWrappedSessionKey = form.getFirst(TRANS_WRAPPED_SESSION_KEY); + sessionWrappedPassphrase = form.getFirst(SESSION_WRAPPED_PASSPHRASE); + nonceData = form.getFirst(NONCE_DATA); + } + + /** + * @return the keyId + */ + public KeyId getKeyId() { + return keyId; + } + + /** + * @param keyId the keyId to set + */ + public void setKeyId(KeyId keyId) { + this.keyId = keyId; + } + + /** + * @return the requestId + */ + public RequestId getRequestId() { + return requestId; + } + + /** + * @param requestId the requestId to set + */ + public void setRequestId(RequestId requestId) { + this.requestId = requestId; + } + + /** + * @return the transWrappedSessionKey + */ + public String getTransWrappedSessionKey() { + return transWrappedSessionKey; + } + + /** + * @param transWrappedSessionKey the transWrappedSessionKey to set + */ + public void setTransWrappedSessionKey(String transWrappedSessionKey) { + this.transWrappedSessionKey = transWrappedSessionKey; + } + + /** + * @return the sessionWrappedPassphrase + */ + public String getSessionWrappedPassphrase() { + return sessionWrappedPassphrase; + } + + /** + * @param sessionWrappedPassphrase the sessionWrappedPassphrase to set + */ + public void setSessionWrappedPassphrase(String sessionWrappedPassphrase) { + this.sessionWrappedPassphrase = sessionWrappedPassphrase; + } + + /** + * @return nonceData + */ + + public String getNonceData() { + return nonceData; + } + + /** + * @param nonceData the nonceData to set + */ + + public void setNonceData(String nonceData) { + this.nonceData = nonceData; + } + +} |