diff options
Diffstat (limited to 'base')
43 files changed, 4811 insertions, 2413 deletions
diff --git a/base/ca/functional/src/com/netscape/cms/servlet/test/CARestClient.java b/base/ca/functional/src/com/netscape/cms/servlet/test/CARestClient.java index 775c3d9b6..67138e529 100644 --- a/base/ca/functional/src/com/netscape/cms/servlet/test/CARestClient.java +++ b/base/ca/functional/src/com/netscape/cms/servlet/test/CARestClient.java @@ -36,6 +36,7 @@ import com.netscape.cms.servlet.profile.model.ProfileData; import com.netscape.cms.servlet.profile.model.ProfileDataInfos; import com.netscape.cms.servlet.request.CertRequestResource; import com.netscape.cms.servlet.request.CertRequestsResource; +import com.netscape.cms.servlet.request.model.AgentEnrollmentRequestData; import com.netscape.cms.servlet.request.model.CertRequestInfo; import com.netscape.cms.servlet.request.model.CertRequestInfos; import com.netscape.cms.servlet.request.model.EnrollmentRequestData; @@ -104,7 +105,7 @@ public class CARestClient extends CMSRestClient { } - public CertRequestInfo enrollCertificate(EnrollmentRequestData data) { + public CertRequestInfos enrollCertificate(EnrollmentRequestData data) { if (data == null) { return null; @@ -113,11 +114,41 @@ public class CARestClient extends CMSRestClient { } public CertRequestInfo getRequest(RequestId id) { - if (id == null) { return null; } return certRequestClient.getRequestInfo(id); } + public AgentEnrollmentRequestData reviewRequest(RequestId id) { + if (id == null) { + return null; + } + return certRequestClient.reviewRequest(id); + } + + public void approveRequest(RequestId id, AgentEnrollmentRequestData data) { + certRequestClient.approveRequest(id, data); + } + + public void rejectRequest(RequestId id, AgentEnrollmentRequestData data) { + certRequestClient.rejectRequest(id, data); + } + + public void cancelRequest(RequestId id, AgentEnrollmentRequestData data) { + certRequestClient.cancelRequest(id, data); + } + + public void updateRequest(RequestId id, AgentEnrollmentRequestData data) { + certRequestClient.updateRequest(id, data); + } + + public void validateRequest(RequestId id, AgentEnrollmentRequestData data) { + certRequestClient.validateRequest(id, data); + } + + public void unassignRequest(RequestId id, AgentEnrollmentRequestData data) { + certRequestClient.unassignRequest(id, data); + } + } diff --git a/base/ca/functional/src/com/netscape/cms/servlet/test/CATest.java b/base/ca/functional/src/com/netscape/cms/servlet/test/CATest.java index c3d55527c..9afb1f386 100644 --- a/base/ca/functional/src/com/netscape/cms/servlet/test/CATest.java +++ b/base/ca/functional/src/com/netscape/cms/servlet/test/CATest.java @@ -45,7 +45,9 @@ import com.netscape.cms.servlet.profile.model.ProfileDataInfo; import com.netscape.cms.servlet.profile.model.ProfileDataInfos; import com.netscape.cms.servlet.profile.model.ProfileInput; import com.netscape.cms.servlet.request.RequestNotFoundException; +import com.netscape.cms.servlet.request.model.AgentEnrollmentRequestData; import com.netscape.cms.servlet.request.model.CertRequestInfo; +import com.netscape.cms.servlet.request.model.CertRequestInfos; import com.netscape.cms.servlet.request.model.EnrollmentRequestData; public class CATest { @@ -203,44 +205,20 @@ public class CATest { //Initiate a Certificate Enrollment - EnrollmentRequestData data = new EnrollmentRequestData(); - data.setProfileId("caUserCert"); - data.setIsRenewal(false); + EnrollmentRequestData data = createUserCertEnrollment(); + enrollAndApproveCertRequest(client, data); - //Simulate a "caUserCert" Profile enrollment - - ProfileInput certReq = data.addInput("Key Generation"); - certReq.setInputAttr("cert_request_type", "crmf"); - certReq.setInputAttr( - "cert_request", - "MIIBozCCAZ8wggEFAgQBMQp8MIHHgAECpQ4wDDEKMAgGA1UEAxMBeKaBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2NgaPHp0jiohcP4M+ufrJOZEqH8GV+liu5JLbT8nWpkfhC+8EUBqT6g+n3qroSxIcNVGNdcsBEqs1utvpItzyslAbpdyat3WwQep1dWMzo6RHrPDuIoxNA0Yka1n3qEX4U//08cLQtUv2bYglYgN/hOCNQemLV6vZWAv0n7zelkCAwEAAakQMA4GA1UdDwEB/wQEAwIF4DAzMBUGCSsGAQUFBwUBAQwIcmVnVG9rZW4wGgYJKwYBBQUHBQECDA1hdXRoZW50aWNhdG9yoYGTMA0GCSqGSIb3DQEBBQUAA4GBAJ1VOQcaSEhdHa94s8kifVbSZ2WZeYE5//qxL6wVlEst20vq4ybj13CetnbN3+WT49Zkwp7Fg+6lALKgSk47suTg3EbbQDm+8yOrC0nc/q4PTRoHl0alMmUxIhirYc1t3xoCMqJewmjX1bNP8lpVIZAYFZo4eZCpZaiSkM5BeHhz"); + // submit a RA authenticated user cert request + EnrollmentRequestData rdata = createRAUserCertEnrollment(); + enrollCertRequest(client, rdata); - ProfileInput subjectName = data.addInput("Subject Name"); - subjectName.setInputAttr("sn_uid", "jmagne"); - subjectName.setInputAttr("sn_e", "jmagne@redhat.com"); - subjectName.setInputAttr("sn_c", "US"); - subjectName.setInputAttr("sn_ou", "Development"); - subjectName.setInputAttr("sn_ou1", "IPA"); - subjectName.setInputAttr("sn_ou2", "Dogtag"); - subjectName.setInputAttr("sn_ou3", "CA"); - subjectName.setInputAttr("sn_cn", "Common"); - subjectName.setInputAttr("sn_o", "RedHat"); - - ProfileInput submitter = data.addInput("Requestor Information"); - submitter.setInputAttr("requestor_name", "admin"); - submitter.setInputAttr("requestor_email", "admin@redhat.com"); - submitter.setInputAttr("requestor_phone", "650-555-5555"); - - CertRequestInfo reqInfo = null; - - try { - reqInfo = client.enrollCertificate(data); - } catch (Exception e) { - e.printStackTrace(); - log(e.toString()); - } + // now try a manually approved server cert + EnrollmentRequestData serverData = createServerCertEnrollment(); + enrollAndApproveCertRequest(client,serverData); - printRequestInfo(reqInfo); + // submit using an agent approval profile + serverData.setProfileId("caAgentServerCert"); + enrollCertRequest(client, serverData); //Perform a sample certificate search with advanced search terms @@ -293,6 +271,120 @@ public class CATest { } + private static void enrollAndApproveCertRequest(CARestClient client, EnrollmentRequestData data) { + CertRequestInfos reqInfo = null; + try { + reqInfo = client.enrollCertificate(data); + } catch (Exception e) { + e.printStackTrace(); + log(e.toString()); + } + + for (CertRequestInfo info : reqInfo.getRequests()) { + printRequestInfo(info); + + AgentEnrollmentRequestData reviewData = client.reviewRequest(info.getRequestId()); + log(reviewData.toString()); + + reviewData.setRequestNotes("This is an approval message"); + client.approveRequest(reviewData.getRequestId(), reviewData); + } + } + + private static void enrollCertRequest(CARestClient client, EnrollmentRequestData data) { + CertRequestInfos reqInfo = null; + try { + reqInfo = client.enrollCertificate(data); + } catch (Exception e) { + e.printStackTrace(); + log(e.toString()); + } + + for (CertRequestInfo info : reqInfo.getRequests()) { + printRequestInfo(info); + } + } + + private static EnrollmentRequestData createUserCertEnrollment() { + EnrollmentRequestData data = new EnrollmentRequestData(); + data.setProfileId("caUserCert"); + data.setIsRenewal(false); + + //Simulate a "caUserCert" Profile enrollment + + ProfileInput certReq = data.createInput("Key Generation"); + certReq.setInputAttr("cert_request_type", "crmf"); + certReq.setInputAttr( + "cert_request", + "MIIBozCCAZ8wggEFAgQBMQp8MIHHgAECpQ4wDDEKMAgGA1UEAxMBeKaBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2NgaPHp0jiohcP4M+ufrJOZEqH8GV+liu5JLbT8nWpkfhC+8EUBqT6g+n3qroSxIcNVGNdcsBEqs1utvpItzyslAbpdyat3WwQep1dWMzo6RHrPDuIoxNA0Yka1n3qEX4U//08cLQtUv2bYglYgN/hOCNQemLV6vZWAv0n7zelkCAwEAAakQMA4GA1UdDwEB/wQEAwIF4DAzMBUGCSsGAQUFBwUBAQwIcmVnVG9rZW4wGgYJKwYBBQUHBQECDA1hdXRoZW50aWNhdG9yoYGTMA0GCSqGSIb3DQEBBQUAA4GBAJ1VOQcaSEhdHa94s8kifVbSZ2WZeYE5//qxL6wVlEst20vq4ybj13CetnbN3+WT49Zkwp7Fg+6lALKgSk47suTg3EbbQDm+8yOrC0nc/q4PTRoHl0alMmUxIhirYc1t3xoCMqJewmjX1bNP8lpVIZAYFZo4eZCpZaiSkM5BeHhz"); + + ProfileInput subjectName = data.createInput("Subject Name"); + subjectName.setInputAttr("sn_uid", "jmagne"); + subjectName.setInputAttr("sn_e", "jmagne@redhat.com"); + subjectName.setInputAttr("sn_c", "US"); + subjectName.setInputAttr("sn_ou", "Development"); + subjectName.setInputAttr("sn_ou1", "IPA"); + subjectName.setInputAttr("sn_ou2", "Dogtag"); + subjectName.setInputAttr("sn_ou3", "CA"); + subjectName.setInputAttr("sn_cn", "Common"); + subjectName.setInputAttr("sn_o", "RedHat"); + + ProfileInput submitter = data.createInput("Requestor Information"); + submitter.setInputAttr("requestor_name", "admin"); + submitter.setInputAttr("requestor_email", "admin@redhat.com"); + submitter.setInputAttr("requestor_phone", "650-555-5555"); + return data; + } + + private static EnrollmentRequestData createRAUserCertEnrollment() { + EnrollmentRequestData data = new EnrollmentRequestData(); + data.setProfileId("caDualRAuserCert"); + data.setIsRenewal(false); + + //Simulate a "caUserCert" Profile enrollment + + ProfileInput certReq = data.createInput("Key Generation"); + certReq.setInputAttr("cert_request_type", "crmf"); + certReq.setInputAttr( + "cert_request", + "MIIB5DCCAeAwggFGAgQTosnaMIIBB4ABAqVOMEwxETAPBgNVBAMTCGFsZWUgcmEzMR4wHAYJKoZIhvcNAQkBFg9hbGVlQHJlZGhhdC5jb20xFzAVBgoJkiaJk/IsZAEBEwdhbGVlcmEzpoGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkQh3k+1323YgQD+oA9yzftqxbGQlsbz0f2OEeOL5h0uhg/qPlSNMjRN3mAeuaNyF0n/Bdxv4699gRTsyEaVJu7HX+kauSCZv+J0tvHiYuHQz1/TSscU9TNLyQjgXVKQFHEdjZa2cQNdmMDUFWrftAK6BFnsP3Tu712qZPAuBH9QIDAQABqRAwDgYDVR0PAQH/BAQDAgXgMDMwFQYJKwYBBQUHBQEBDAhyZWdUb2tlbjAaBgkrBgEFBQcFAQIMDWF1dGhlbnRpY2F0b3KhgZMwDQYJKoZIhvcNAQEFBQADgYEATNi3vMxn9KMto999sR4ik851jqbb6L0GL1KKgQ/hjIAACQb2H+0OpqeZ2+DcGd+oAQn1YZe8aPoFu+HOWjHlY1E2tm7TI1B6JpCL3TMag3mYryROX7l7LFEa1P730aGOWJF874bG8UWisU190zhCBQUqUjsd9DwaP42qM0gnzas="); + + ProfileInput subjectName = data.createInput("Subject Name"); + subjectName.setInputAttr("sn_uid", "aleera3"); + subjectName.setInputAttr("sn_e", "alee@redhat.com"); + subjectName.setInputAttr("sn_cn", "alee ra3"); + + ProfileInput submitter = data.createInput("Requestor Information"); + submitter.setInputAttr("requestor_name", "admin"); + submitter.setInputAttr("requestor_email", "admin@redhat.com"); + submitter.setInputAttr("requestor_phone", "650-555-1234"); + return data; + } + + private static EnrollmentRequestData createServerCertEnrollment() { + EnrollmentRequestData data = new EnrollmentRequestData(); + data.setProfileId("caServerCert"); + data.setIsRenewal(false); + + //Simulate a "caUserCert" Profile enrollment + + ProfileInput certReq = data.createInput("Key Generation"); + certReq.setInputAttr("cert_request_type", "pkcs10"); + certReq.setInputAttr( + "cert_request", + "MIIBZjCB0AIBADAnMQ8wDQYDVQQKEwZyZWRoYXQxFDASBgNVBAMTC2FsZWUtd29ya3BjMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJtuKg9osJEBUwz8LoMQwwm1m7D97NNJEmvEhvBMet+VCtbd/erAFMoVXEgSKks/XFK2ViTeZYpp0A2pe4bm4yxowZm0b6von9BKGQ0jNtLemoOkGRWC/PP+fYP16aH62xu4z8MH1pBubdlAEp3Ppnr93aB1lzQaPVmcR3B4OWhwIDAQABoAAwDQYJKoZIhvcNAQEFBQADgYEAgZhZOe0LqQD5iywAO7sY0PANVGzzdcmoLZJjjASY3kU5E3K8u3FKh24WJxcWzdC+/FysDkJixJb7xGUm697QwZvGxmAIQH4yIebWJ2KLHQQgRJytjVYySrRo2Fuo/dm2zzf3+o8WBuD2eMsEjsZfuKxhz7EahvyC2y/CuTBA08s=" + ); + ProfileInput subjectName = data.createInput("Subject Name"); + subjectName.setInputAttr("sn_cn", "alee-workpc"); + subjectName.setInputAttr("sn_o", "redhat"); + + ProfileInput submitter = data.createInput("Requestor Information"); + submitter.setInputAttr("requestor_name", "admin"); + submitter.setInputAttr("requestor_email", "admin@redhat.com"); + submitter.setInputAttr("requestor_phone", "650-555-5555"); + return data; + } + private static void printProfileInfos(ProfileDataInfos pInfos) { if (pInfos == null) { @@ -451,11 +543,11 @@ public class CATest { } log("CertRequestURL: " + info.getRequestURL()); - log("CertId: " + info.getCertId()); + log("CertId: " + ((info.getCertId() != null) ? info.getCertId() : "")); log("RequestType: " + info.getCertRequestType()); log("Status: " + info.getRequestStatus()); log("Type: " + info.getRequestType()); - log("CertURL: " + info.getCertURL() + "\n"); + log("CertURL: " + ((info.getCertURL() != null) ? info.getCertURL(): "") + "\n"); } private static void log(String string) { diff --git a/base/ca/shared/conf/CS.cfg.in b/base/ca/shared/conf/CS.cfg.in index ada97c4fa..527de831d 100644 --- a/base/ca/shared/conf/CS.cfg.in +++ b/base/ca/shared/conf/CS.cfg.in @@ -1056,6 +1056,15 @@ profile.caEncUserCert.config=[PKI_INSTANCE_PATH]/profiles/ca/caEncUserCert.cfg profile.caEncECUserCert.class_id=caEnrollImpl profile.caEncECUserCert.config=[PKI_INSTANCE_PATH]/profiles/ca/caEncECUserCert.cfg registry.file=[PKI_INSTANCE_PATH]/conf/registry.cfg +profile.caProfileProcess.getClientCert=true +profile.caProfileProcess.authzMgr=BasicAclAuthz +profile.caProfileProcess.authorityId=ca +profile.caProfileProcess.authzResourceName=certServer.ca.request.profile +profile.caProfileProcess.authMgr=certUserDBAuthMgr +profile.caProfileSubmit.authorityId=ca +profile.caProfileSubmit.authzMgr=BasicAclAuthz +profile.caProfileSubmit.authzResourceName=certServer.ee.profile +profile.caProfileSubmit.getClientCert=false request.assignee.enable=true selftests._000=## selftests._001=## Self Tests diff --git a/base/common/src/CMakeLists.txt b/base/common/src/CMakeLists.txt index 7b73a8536..6d8386faf 100644 --- a/base/common/src/CMakeLists.txt +++ b/base/common/src/CMakeLists.txt @@ -251,6 +251,7 @@ set(pki-certsrv_java_SRCS com/netscape/certsrv/base/IAttrSet.java com/netscape/certsrv/base/ICRLPrettyPrint.java com/netscape/certsrv/base/ICertPrettyPrint.java + com/netscape/certsrv/base/BadRequestDataException.java com/netscape/certsrv/dbs/IDBRegistry.java com/netscape/certsrv/dbs/IDBAttrMapper.java com/netscape/certsrv/dbs/IElementProcessor.java @@ -614,6 +615,10 @@ set(pki-cms_java_SRCS com/netscape/cms/servlet/cert/CertResourceService.java com/netscape/cms/servlet/cert/CertsResource.java com/netscape/cms/servlet/cert/CertsResourceService.java + com/netscape/cms/servlet/cert/RequestProcessor.java + com/netscape/cms/servlet/cert/CertProcessor.java + com/netscape/cms/servlet/cert/EnrollmentProcessor.java + com/netscape/cms/servlet/cert/RenewalProcessor.java com/netscape/cms/servlet/cert/model/CertificateData.java com/netscape/cms/servlet/cert/model/CertDAO.java com/netscape/cms/servlet/cert/model/CertDataInfo.java @@ -746,6 +751,7 @@ set(pki-cms_java_SRCS com/netscape/cms/servlet/processors/CRMFProcessor.java com/netscape/cms/servlet/processors/IPKIProcessor.java com/netscape/cms/servlet/processors/CMCProcessor.java + com/netscape/cms/servlet/processors/Processor.java com/netscape/cms/servlet/request/ProcessReq.java com/netscape/cms/servlet/request/CheckRequest.java com/netscape/cms/servlet/request/IReqParser.java @@ -776,8 +782,12 @@ set(pki-cms_java_SRCS com/netscape/cms/servlet/request/model/CertRequestInfo.java com/netscape/cms/servlet/request/model/CertRequestInfos.java com/netscape/cms/servlet/request/model/CertRetrievalRequestData.java + com/netscape/cms/servlet/request/model/AgentEnrollmentRequestData.java com/netscape/cms/servlet/request/model/EnrollmentRequestData.java com/netscape/cms/servlet/request/model/ProfileRetrievalRequestData.java + com/netscape/cms/servlet/request/model/AgentEnrollmentRequestDataFactory.java + com/netscape/cms/servlet/request/model/CertRequestInfoFactory.java + com/netscape/cms/servlet/request/model/EnrollmentRequestDataFactory.java com/netscape/cms/servlet/tks/TokenServlet.java com/netscape/cms/servlet/connector/CloneServlet.java com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java @@ -809,6 +819,17 @@ set(pki-cms_java_SRCS com/netscape/cms/servlet/profile/model/ProfileDataInfo.java com/netscape/cms/servlet/profile/model/ProfileDataInfos.java com/netscape/cms/servlet/profile/model/ProfileInput.java + com/netscape/cms/servlet/profile/model/ProfileAttribute.java + com/netscape/cms/servlet/profile/model/PolicyConstraint.java + com/netscape/cms/servlet/profile/model/PolicyConstraintValue.java + com/netscape/cms/servlet/profile/model/PolicyDefault.java + com/netscape/cms/servlet/profile/model/ProfileInput.java + com/netscape/cms/servlet/profile/model/ProfilePolicy.java + com/netscape/cms/servlet/profile/model/ProfilePolicySet.java + com/netscape/cms/servlet/profile/model/PolicyConstraintFactory.java + com/netscape/cms/servlet/profile/model/PolicyDefaultFactory.java + com/netscape/cms/servlet/profile/model/ProfileInputFactory.java + com/netscape/cms/servlet/profile/model/ProfileOutputFactory.java com/netscape/cms/authentication/AgentCertAuthentication.java com/netscape/cms/authentication/PortalEnroll.java com/netscape/cms/authentication/UdnPwdDirAuthentication.java diff --git a/base/common/src/com/netscape/certsrv/base/BadRequestDataException.java b/base/common/src/com/netscape/certsrv/base/BadRequestDataException.java new file mode 100644 index 000000000..268221eae --- /dev/null +++ b/base/common/src/com/netscape/certsrv/base/BadRequestDataException.java @@ -0,0 +1,24 @@ +package com.netscape.certsrv.base; + +public class BadRequestDataException extends EBaseException { + + private static final long serialVersionUID = -8401421856920994265L; + + + public BadRequestDataException(String msgFormat) { + super(msgFormat); + } + + public BadRequestDataException(String msgFormat, Exception param) { + super(msgFormat, param); + } + + public BadRequestDataException(String msgFormat, Object[] params) { + super(msgFormat, params); + } + + public BadRequestDataException(String msgFormat, String param) { + super(msgFormat, param); + } + +} diff --git a/base/common/src/com/netscape/certsrv/property/Descriptor.java b/base/common/src/com/netscape/certsrv/property/Descriptor.java index 4b2baf561..d3048e0b9 100644 --- a/base/common/src/com/netscape/certsrv/property/Descriptor.java +++ b/base/common/src/com/netscape/certsrv/property/Descriptor.java @@ -19,12 +19,19 @@ package com.netscape.certsrv.property; import java.util.Locale; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + + /** * This interface represents a property descriptor. A descriptor * includes information that describe a property. * * @version $Revision$, $Date$ */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) public class Descriptor implements IDescriptor { protected String mSyntax = null; @@ -32,6 +39,10 @@ public class Descriptor implements IDescriptor { protected String mDescription = null; protected String mDef = null; + public Descriptor() { + // required for JAX-B + } + /** * Constructs a descriptor. * @@ -90,4 +101,10 @@ public class Descriptor implements IDescriptor { public String getDescription(Locale locale) { return mDescription; } + + @Override + public String toString() { + return "Descriptor [mSyntax=" + mSyntax + ", mConstraint=" + mConstraint + ", mDescription=" + mDescription + + ", mDef=" + mDef + "]"; + } } diff --git a/base/common/src/com/netscape/certsrv/request/RequestId.java b/base/common/src/com/netscape/certsrv/request/RequestId.java index 795fdaa2a..8cd8c5711 100644 --- a/base/common/src/com/netscape/certsrv/request/RequestId.java +++ b/base/common/src/com/netscape/certsrv/request/RequestId.java @@ -31,6 +31,10 @@ public class RequestId { protected BigInteger value; + public RequestId() { + // required for jaxb + } + /** * Creates a new RequestId from its string representation. * <p> diff --git a/base/common/src/com/netscape/cms/servlet/base/CMSResourceService.java b/base/common/src/com/netscape/cms/servlet/base/CMSResourceService.java index 85ccbf9f7..d6b4a9e42 100644 --- a/base/common/src/com/netscape/cms/servlet/base/CMSResourceService.java +++ b/base/common/src/com/netscape/cms/servlet/base/CMSResourceService.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import javax.servlet.http.HttpServletRequest; import javax.ws.rs.FormParam; import javax.ws.rs.core.CacheControl; import javax.ws.rs.core.Context; @@ -62,6 +63,9 @@ public class CMSResourceService { @Context protected Request request; + @Context + protected HttpServletRequest servletRequest; + public ILogger logger = CMS.getLogger(); public IAuditor auditor = CMS.getAuditor(); diff --git a/base/common/src/com/netscape/cms/servlet/base/CMSServlet.java b/base/common/src/com/netscape/cms/servlet/base/CMSServlet.java index 1c610996f..f035285e2 100644 --- a/base/common/src/com/netscape/cms/servlet/base/CMSServlet.java +++ b/base/common/src/com/netscape/cms/servlet/base/CMSServlet.java @@ -117,6 +117,7 @@ public abstract class CMSServlet extends HttpServlet { public final static String PROP_ID = "ID"; public final static String PROP_AUTHORITY = "authority"; + public final static String PROP_AUTHORITYID = "authorityId"; public final static String PROP_AUTHMGR = "AuthMgr"; public final static String PROP_CLIENTAUTH = "GetClientCert"; public final static String PROP_RESOURCEID = "resourceID"; @@ -291,6 +292,9 @@ public abstract class CMSServlet extends HttpServlet { mOutputTemplatePath = sc.getInitParameter("templatePath"); String authority = sc.getInitParameter(PROP_AUTHORITY); + if (authority == null) { + authority = sc.getInitParameter(PROP_AUTHORITYID); + } if (authority != null) mAuthority = (IAuthority) diff --git a/base/common/src/com/netscape/cms/servlet/cert/CertProcessor.java b/base/common/src/com/netscape/cms/servlet/cert/CertProcessor.java new file mode 100644 index 000000000..13b0072b4 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/CertProcessor.java @@ -0,0 +1,351 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.cert; + +import java.math.BigInteger; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.EPropertyNotFound; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.EDeferException; +import com.netscape.certsrv.profile.ERejectException; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileAuthenticator; +import com.netscape.certsrv.profile.IProfileContext; +import com.netscape.certsrv.profile.IProfileInput; +import com.netscape.certsrv.request.INotify; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.processors.Processor; +import com.netscape.cms.servlet.profile.model.ProfileInput; +import com.netscape.cms.servlet.request.model.EnrollmentRequestData; + +public class CertProcessor extends Processor { + + public CertProcessor(String id, Locale locale) throws EPropertyNotFound, EBaseException { + super(id, locale); + } + + protected void setCredentialsIntoContext(HttpServletRequest request, IProfileAuthenticator authenticator, + IProfileContext ctx) { + Enumeration<String> authIds = authenticator.getValueNames(); + + if (authIds != null) { + CMS.debug("CertRequestSubmitter:setCredentialsIntoContext() authNames not null"); + while (authIds.hasMoreElements()) { + String authName = authIds.nextElement(); + + CMS.debug("CertRequestSubmitter:setCredentialsIntoContext() authName:" + + authName); + if (request.getParameter(authName) != null) { + CMS.debug("CertRequestSubmitter:setCredentialsIntoContext() authName found in request"); + ctx.set(authName, request.getParameter(authName)); + } else { + CMS.debug("CertRequestSubmitter:setCredentialsIntoContext() authName not found in request"); + } + } + } else { + CMS.debug("CertRequestSubmitter:setCredentialsIntoContext() authIds` null"); + } + } + + private void setInputsIntoRequest(EnrollmentRequestData data, IProfile profile, IRequest req) { + // put profile inputs into a local map + HashMap<String, String> dataInputs = new HashMap<String, String>(); + for (ProfileInput input : data.getInputs()) { + Map<String, String> attrs = input.getAttributes(); + for (Map.Entry<String, String> entry : attrs.entrySet()) { + dataInputs.put(entry.getKey(), entry.getValue()); + } + } + + // iterate over inputs in profile + Enumeration<String> inputIds = profile.getProfileInputIds(); + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration<String> inputNames = profileInput.getValueNames(); + + if (inputNames != null) { + while (inputNames.hasMoreElements()) { + String inputName = inputNames.nextElement(); + if (dataInputs.containsKey(inputName)) { + // special characters in subject names parameters must be escaped + if (inputName.matches("^sn_.*")) { + req.setExtData(inputName, + escapeValueRfc1779(dataInputs.get(inputName), false) + .toString()); + } else { + req.setExtData(inputName, dataInputs.get(inputName)); + } + } + } + } + } + } + } + + /* + * fill input info from orig request to the renew request. + * This is expected to be used by renewal where the request + * is retrieved from request record + */ + private void setInputsIntoRequest(IRequest request, IProfile profile, IRequest req, Locale locale) { + // passing inputs into request + Enumeration<String> inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration<String> inputNames = profileInput.getValueNames(); + + while (inputNames.hasMoreElements()) { + String inputName = inputNames.nextElement(); + String inputValue = ""; + CMS.debug("CertRequestSubmitter: setInputsIntoRequest() getting input name= " + inputName); + try { + inputValue = profileInput.getValue(inputName, locale, request); + } catch (Exception e) { + CMS.debug("CertRequestSubmitter: setInputsIntoRequest() getvalue() failed: " + e.toString()); + } + + if (inputValue != null) { + CMS.debug("CertRequestSubmitter: setInputsIntoRequest() setting value in ctx:" + inputValue); + req.setExtData(inputName, inputValue); + } else { + CMS.debug("CertRequestSubmitter: setInputsIntoRequest() value null"); + } + } + } + } + + } + + protected String codeToReason(Locale locale, String errorCode) { + if (errorCode == null) return null; + if (errorCode.equals("1")) { + return CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR"); + } else if (errorCode.equals("2")) { + return CMS.getUserMessage(locale, "CMS_PROFILE_DEFERRED"); + } else if (errorCode.equals("3")) { + return CMS.getUserMessage(locale, "CMS_PROFILE_REJECTED"); + } + return null; + } + + protected String submitRequests(Locale locale, IProfile profile, IAuthToken authToken, IRequest[] reqs) { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = ILogger.UNIDENTIFIED; + String auditInfoCertValue = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + String errorCode = null; + String errorReason = null; + + for (IRequest req : reqs) { + try { + // reset the "auditRequesterID" + auditRequesterID = auditRequesterID(req); + + // print request debug + if (req != null) { + Enumeration<String> reqKeys = req.getExtDataKeys(); + while (reqKeys.hasMoreElements()) { + String reqKey = reqKeys.nextElement(); + String reqVal = req.getExtDataInString(reqKey); + if (reqVal != null) { + CMS.debug("CertRequestSubmitter: key=$request." + reqKey + "$ value=" + reqVal); + } + } + } + + profile.submit(authToken, req); + req.setRequestStatus(RequestStatus.COMPLETE); + + // reset the "auditInfoCertValue" + auditInfoCertValue = auditInfoCertValue(req); + + if (auditInfoCertValue != null) { + if (!(auditInfoCertValue.equals( + ILogger.SIGNED_AUDIT_EMPTY_VALUE))) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + ILogger.SIGNED_AUDIT_ACCEPTANCE, + auditInfoCertValue); + + audit(auditMessage); + } + } + } catch (EDeferException e) { + // return defer message to the user + req.setRequestStatus(RequestStatus.PENDING); + // need to notify + INotify notify = profile.getRequestQueue().getPendingNotify(); + if (notify != null) { + notify.notify(req); + } + + CMS.debug("CertRequestSubmitter: submit " + e.toString()); + errorCode = "2"; + errorReason = CMS.getUserMessage(locale, "CMS_PROFILE_DEFERRED", e.toString()); + + // do NOT store a message in the signed audit log file + // as this errorCode indicates that a process has been + // deferred for manual acceptance/cancellation/rejection + } catch (ERejectException e) { + // return error to the user + req.setRequestStatus(RequestStatus.REJECTED); + CMS.debug("CertRequestSubmitter: submit " + e.toString()); + errorCode = "3"; + errorReason = CMS.getUserMessage(locale, "CMS_PROFILE_REJECTED", e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + ILogger.SIGNED_AUDIT_REJECTION, + errorReason); + + audit(auditMessage); + } catch (Throwable e) { + // return error to the user + e.printStackTrace(); + CMS.debug("CertRequestSubmitter: submit " + e.toString()); + errorCode = "1"; + errorReason = CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR"); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + ILogger.SIGNED_AUDIT_REJECTION, + errorReason); + + audit(auditMessage); + } + + try { + if (errorCode == null) { + profile.getRequestQueue().markAsServiced(req); + } else { + profile.getRequestQueue().updateRequest(req); + } + } catch (EBaseException e) { + e.printStackTrace(); + CMS.debug("CertRequestSubmitter: updateRequest " + e.toString()); + } + } + return errorCode; + } + + protected void populateRequests(EnrollmentRequestData data, boolean isRenewal, + Locale locale, Date origNotAfter, String origSubjectDN, IRequest origReq, String profileId, + IProfile profile, IProfileContext ctx, IProfileAuthenticator authenticator, IAuthToken authToken, + IRequest[] reqs) throws EBaseException { + for (IRequest req : reqs) { + boolean fromRA = false; + String uid = ""; + + // adding parameters to request + if (isRenewal) { + setInputsIntoRequest(origReq, profile, req, locale); + req.setExtData("origNotAfter", BigInteger.valueOf(origNotAfter.getTime())); + req.setExtData(IProfileAuthenticator.AUTHENTICATED_NAME, origSubjectDN); + req.setRequestType("renewal"); + } else { + setInputsIntoRequest(data, profile, req); + } + + // serial auth token into request + if (authToken != null) { + Enumeration<String> tokenNames = authToken.getElements(); + while (tokenNames.hasMoreElements()) { + String tokenName = tokenNames.nextElement(); + String[] tokenVals = authToken.getInStringArray(tokenName); + if (tokenVals != null) { + for (int i = 0; i < tokenVals.length; i++) { + req.setExtData(ARG_AUTH_TOKEN + "." + tokenName + "[" + i + "]", tokenVals[i]); + } + } else { + String tokenVal = authToken.getInString(tokenName); + if (tokenVal != null) { + req.setExtData(ARG_AUTH_TOKEN + "." + tokenName, tokenVal); + // if RA agent, auto assign the request + if (tokenName.equals("uid")) + uid = tokenVal; + if (tokenName.equals("group") && tokenVal.equals("Registration Manager Agents")) { + fromRA = true; + } + } + } + } + } + + if (fromRA) { + CMS.debug("CertRequestSubmitter: request from RA: " + uid); + req.setExtData(ARG_REQUEST_OWNER, uid); + } + + // put profile framework parameters into the request + req.setExtData(ARG_PROFILE, "true"); + req.setExtData(ARG_PROFILE_ID, profileId); + if (isRenewal) + req.setExtData(ARG_RENEWAL_PROFILE_ID, data.getProfileId()); + req.setExtData(ARG_PROFILE_APPROVED_BY, profile.getApprovedBy()); + String setId = profile.getPolicySetId(req); + + if (setId == null) { + // no profile set found + CMS.debug("CertRequestSubmitter: no profile policy set found"); + throw new EBaseException(CMS.getUserMessage(locale, "CMS_PROFILE_NO_POLICY_SET_FOUND")); + } + + CMS.debug("CertRequestSubmitter profileSetid=" + setId); + req.setExtData(ARG_PROFILE_SET_ID, setId); + req.setExtData(ARG_PROFILE_REMOTE_HOST, data.getRemoteHost()); + req.setExtData(ARG_PROFILE_REMOTE_ADDR, data.getRemoteAddr()); + + CMS.debug("CertRequestSubmitter: request " + req.getRequestId().toString()); + + CMS.debug("CertRequestSubmitter: populating request inputs"); + // give authenticator a chance to populate the request + if (authenticator != null) { + authenticator.populate(authToken, req); + } + profile.populateInput(ctx, req); + profile.populate(req); + } + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java b/base/common/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java new file mode 100644 index 000000000..8b48f0d73 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java @@ -0,0 +1,205 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.cert; + +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.BadRequestDataException; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.EPropertyNotFound; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileAuthenticator; +import com.netscape.certsrv.profile.IProfileContext; +import com.netscape.certsrv.profile.IProfileInput; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.profile.SSLClientCertProvider; +import com.netscape.cms.servlet.profile.model.ProfileInput; +import com.netscape.cms.servlet.request.model.EnrollmentRequestData; +import com.netscape.cms.servlet.request.model.EnrollmentRequestDataFactory; + +public class EnrollmentProcessor extends CertProcessor { + + public EnrollmentProcessor(String id, Locale locale) throws EPropertyNotFound, EBaseException { + super(id, locale); + } + + private void setInputsIntoContext(EnrollmentRequestData data, IProfile profile, IProfileContext ctx) { + // put profile inputs into a local map + HashMap<String, String> dataInputs = new HashMap<String, String>(); + for (ProfileInput input : data.getInputs()) { + Map<String, String> attrs = input.getAttributes(); + for (Map.Entry<String, String> entry : attrs.entrySet()) { + dataInputs.put(entry.getKey(), entry.getValue()); + } + } + + // iterate through inputs in profile and put those in context + Enumeration<String> inputIds = profile.getProfileInputIds(); + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration<String> inputNames = profileInput.getValueNames(); + + while (inputNames.hasMoreElements()) { + String inputName = inputNames.nextElement(); + if (dataInputs.containsKey(inputName)) { + // all subject name parameters start with sn_, no other input parameters do + if (inputName.matches("^sn_.*")) { + ctx.set(inputName, escapeValueRfc1779(dataInputs.get(inputName), false).toString()); + } else { + ctx.set(inputName, dataInputs.get(inputName)); + } + } + } + } + } + + } + + /** + * Called by the legacy servlets to access the Processor function + * @param request + * @return + * @throws EBaseException + */ + public HashMap<String, Object> processEnrollment(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + String profileId = (this.profileID == null) ? req.getParameter("profileId") : this.profileID; + IProfile profile = ps.getProfile(profileId); + + if (profile == null) { + CMS.debug(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); + throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); + } + + EnrollmentRequestData data = EnrollmentRequestDataFactory.create(cmsReq, profile, locale); + return processEnrollment(data, cmsReq.getHttpReq()); + } + + /** + * Process the HTTP request + * <P> + * + * (Certificate Request Processed - either an automated "EE" profile based cert acceptance, or an automated "EE" + * profile based cert rejection) + * <P> + * + * <ul> + * <li>http.param profileId ID of profile to use to process request + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + * </ul> + * + * @param cmsReq the object holding the request and response information + * @exception EBaseException an error has occurred + */ + public HashMap<String, Object> processEnrollment(EnrollmentRequestData data, HttpServletRequest request) + throws EBaseException { + + try { + if (CMS.debugOn()) { + HashMap<String,String> params = data.toParams(); + printParameterValues(params); + } + + CMS.debug("EnrollmentSubmitter: isRenewal false"); + startTiming("enrollment"); + + // if we did not configure profileId in xml file, + // then accept the user-provided one + String profileId = (this.profileID == null) ? data.getProfileId() : this.profileID; + CMS.debug("EnrollmentSubmitter: profileId " + profileId); + + IProfile profile = ps.getProfile(profileId); + if (profile == null) { + CMS.debug(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); + throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); + } + if (!ps.isProfileEnable(profileId)) { + CMS.debug("EnrollmentSubmitter: Profile " + profileId + " not enabled"); + throw new BadRequestDataException("Profile " + profileId + " not enabled"); + } + + IProfileContext ctx = profile.createContext(); + CMS.debug("EnrollmentSubmitter: set Inputs into profile Context"); + setInputsIntoContext(data, profile, ctx); + + IProfileAuthenticator authenticator = profile.getAuthenticator(); + if (authenticator != null) { + CMS.debug("EnrollmentSubmitter: authenticator " + authenticator.getName() + " found"); + setCredentialsIntoContext(request, authenticator, ctx); + } + + // for ssl authentication; pass in servlet for retrieving ssl client certificates + // insert profile context so that input parameter can be retrieved + SessionContext context = SessionContext.getContext(); + context.put("profileContext", ctx); + context.put("sslClientCertProvider", new SSLClientCertProvider(request)); + CMS.debug("EnrollmentSubmitter: set sslClientCertProvider"); + + // before creating the request, authenticate the request + IAuthToken authToken = authenticate(request, null, authenticator, context, false); + + // authentication success, now authorize + authorize(profileId, profile, authToken); + + /////////////////////////////////////////////// + // create and populate request + /////////////////////////////////////////////// + startTiming("request_population"); + IRequest[] reqs = profile.createRequests(ctx, locale); + populateRequests(data, false, locale, null, null, null, profileId, profile, + ctx, authenticator, authToken, reqs); + endTiming("request_population"); + + /////////////////////////////////////////////// + // submit request + /////////////////////////////////////////////// + String errorCode = submitRequests(locale, profile, authToken, reqs); + String errorReason = codeToReason(locale, errorCode); + + HashMap<String, Object> ret = new HashMap<String, Object>(); + ret.put(ARG_REQUESTS, reqs); + ret.put(ARG_ERROR_CODE, errorCode); + ret.put(ARG_ERROR_REASON, errorReason); + ret.put(ARG_PROFILE, profile); + + CMS.debug("EnrollmentSubmitter: done serving"); + endTiming("enrollment"); + + return ret; + } finally { + SessionContext.releaseContext(); + endAllEvents(); + } + } + + + + +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/RenewalProcessor.java b/base/common/src/com/netscape/cms/servlet/cert/RenewalProcessor.java new file mode 100644 index 000000000..cc4dd12ae --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/RenewalProcessor.java @@ -0,0 +1,345 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.cert; + +import java.math.BigInteger; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Locale; + +import javax.servlet.http.HttpServletRequest; + +import netscape.security.x509.BasicConstraintsExtension; +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.BadRequestDataException; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.EPropertyNotFound; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileAuthenticator; +import com.netscape.certsrv.profile.IProfileContext; +import com.netscape.certsrv.profile.IProfileInput; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.profile.SSLClientCertProvider; +import com.netscape.cms.servlet.request.model.EnrollmentRequestData; +import com.netscape.cms.servlet.request.model.EnrollmentRequestDataFactory; + +public class RenewalProcessor extends CertProcessor { + + public RenewalProcessor(String id, Locale locale) throws EPropertyNotFound, EBaseException { + super(id, locale); + } + + public HashMap<String, Object> processRenewal(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + String profileId = (this.profileID == null) ? req.getParameter("profileId") : this.profileID; + IProfile profile = ps.getProfile(profileId); + if (profile == null) { + throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); + } + + EnrollmentRequestData data = EnrollmentRequestDataFactory.create(cmsReq, profile, locale); + + //only used in renewal + data.setSerialNum(req.getParameter("serial_num")); + + return processRenewal(data, req); + } + + /* + * Renewal - Renewal is retrofitted into the Profile Enrollment + * Framework. The authentication and authorization are taken from + * the renewal profile, while the input (with requests) and grace + * period constraint are taken from the original cert's request record. + * + * Things to note: + * * the renew request will contain the original profile instead of the new + */ + public HashMap<String, Object> processRenewal(EnrollmentRequestData data, HttpServletRequest request) + throws EBaseException { + try { + if (CMS.debugOn()) { + HashMap<String,String> params = data.toParams(); + printParameterValues(params); + } + CMS.debug("RenewalSubmitter: isRenewal true"); + + startTiming("enrollment"); + request.setAttribute("reqType", "renewal"); + + // in case of renew, "profile" is the orig profile + // while "renewProfile" is the current profile used for renewal + String renewProfileId = (this.profileID == null) ? data.getProfileId() : this.profileID; + CMS.debug("processRenewal: renewProfileId " + renewProfileId); + + IProfile renewProfile = ps.getProfile(renewProfileId); + if (renewProfile == null) { + CMS.debug(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", renewProfileId)); + throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", renewProfileId)); + } + if (!ps.isProfileEnable(renewProfileId)) { + CMS.debug("RenewalSubmitter: Profile " + renewProfileId + " not enabled"); + throw new BadRequestDataException("Profile " + renewProfileId + " not enabled"); + } + + String serial = data.getSerialNum(); + BigInteger certSerial = null; + + if (serial != null) { + // if serial number is sent with request, then the authentication + // method is not ssl client auth. In this case, an alternative + // authentication method is used (default: ldap based) + // usr_origreq evaluator should be used to authorize ownership + // of the cert + CMS.debug("RenewalSubmitter: renewal: found serial_num"); + certSerial = new BigInteger(serial); + } else { + // ssl client auth is to be used + // this is not authentication. Just use the cert to search + // for orig request and find the right profile + CMS.debug("RenewalSubmitter: renewal: serial_num not found, must do ssl client auth"); + certSerial = getSerialNumberFromCert(request); + if (certSerial == null) { + CMS.debug(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + throw new EBaseException(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } + } + CMS.debug("processRenewal: serial number of cert to renew:" + certSerial.toString()); + ICertRecord rec = certdb.readCertificateRecord(certSerial); + if (rec == null) { + CMS.debug("processRenewal: cert record not found for serial number " + certSerial.toString()); + throw new EBaseException(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } + + // check to see if the cert is revoked or revoked_expired + if ((rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) + || (rec.getStatus().equals(ICertRecord.STATUS_REVOKED_EXPIRED))) { + CMS.debug("processRenewal: cert found to be revoked. Serial number = " + + certSerial.toString()); + throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_CA_CANNOT_RENEW_REVOKED_CERT")); + } + + X509CertImpl origCert = rec.getCertificate(); + if (origCert == null) { + CMS.debug("processRenewal: original cert not found in cert record for serial number " + + certSerial.toString()); + throw new EBaseException(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } + + Date origNotAfter = origCert.getNotAfter(); + CMS.debug("processRenewal: origNotAfter =" + origNotAfter.toString()); + + String origSubjectDN = origCert.getSubjectDN().getName(); + CMS.debug("processRenewal: orig subj dn =" + origSubjectDN); + + IRequest origReq = getOriginalRequest(certSerial, rec); + if (origReq == null) { + CMS.debug("processRenewal: original request not found"); + throw new EBaseException(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } + + String profileId = origReq.getExtDataInString("profileId"); + CMS.debug("RenewalSubmitter: renewal original profileId=" + profileId); + + Integer origSeqNum = origReq.getExtDataInInteger(IEnrollProfile.REQUEST_SEQ_NUM); + IProfile profile = ps.getProfile(profileId); + if (profile == null) { + CMS.debug(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); + throw new EBaseException(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); + } + if (!ps.isProfileEnable(profileId)) { + CMS.debug("RenewalSubmitter: Profile " + profileId + " not enabled"); + throw new BadRequestDataException("Profile " + profileId + " not enabled"); + } + + IProfileContext ctx = profile.createContext(); + IProfileAuthenticator authenticator = renewProfile.getAuthenticator(); + IProfileAuthenticator origAuthenticator = profile.getAuthenticator(); + + if (authenticator != null) { + CMS.debug("RenewalSubmitter: authenticator " + authenticator.getName() + " found"); + setCredentialsIntoContext(request, authenticator, ctx); + } + + // for renewal, this will override or add auth info to the profile context + if (origAuthenticator != null) { + CMS.debug("RenewalSubmitter: for renewal, original authenticator " + + origAuthenticator.getName() + " found"); + setCredentialsIntoContext(request, origAuthenticator, ctx); + } + + // for renewal, input needs to be retrieved from the orig req record + CMS.debug("processRenewal: set original Inputs into profile Context"); + setInputsIntoContext(origReq, profile, ctx, locale); + ctx.set(IEnrollProfile.CTX_RENEWAL, "true"); + ctx.set("renewProfileId", renewProfileId); + ctx.set(IEnrollProfile.CTX_RENEWAL_SEQ_NUM, origSeqNum.toString()); + + // for ssl authentication; pass in servlet for retrieving + // ssl client certificates + SessionContext context = SessionContext.getContext(); + context.put("profileContext", ctx); + context.put("sslClientCertProvider", new SSLClientCertProvider(request)); + CMS.debug("RenewalSubmitter: set sslClientCertProvider"); + if (origSubjectDN != null) + context.put("origSubjectDN", origSubjectDN); + + // before creating the request, authenticate the request + IAuthToken authToken = authenticate(request, origReq, authenticator, context, true); + + // authentication success, now authorize + authorize(profileId, renewProfile, authToken); + + /////////////////////////////////////////////// + // create and populate requests + /////////////////////////////////////////////// + startTiming("request_population"); + IRequest[] reqs = profile.createRequests(ctx, locale); + populateRequests(data, true, locale, origNotAfter, origSubjectDN, origReq, profileId, + profile, ctx, authenticator, authToken, reqs); + endTiming("request_population"); + + /////////////////////////////////////////////// + // submit request + /////////////////////////////////////////////// + String errorCode = submitRequests(locale, profile, authToken, reqs); + String errorReason = codeToReason(locale, errorCode); + + HashMap<String, Object> ret = new HashMap<String, Object>(); + ret.put(ARG_REQUESTS, reqs); + ret.put(ARG_ERROR_CODE, errorCode); + ret.put(ARG_ERROR_REASON, errorReason); + ret.put(ARG_PROFILE, profile); + + CMS.debug("RenewalSubmitter: done serving"); + endTiming("enrollment"); + + return ret; + } finally { + SessionContext.releaseContext(); + endAllEvents(); + } + } + + private BigInteger getSerialNumberFromCert(HttpServletRequest request) throws EBaseException { + BigInteger certSerial; + SSLClientCertProvider sslCCP = new SSLClientCertProvider(request); + X509Certificate[] certs = sslCCP.getClientCertificateChain(); + certSerial = null; + if (certs == null || certs.length == 0) { + CMS.debug("RenewalSubmitter: renewal: no ssl client cert chain"); + return null; + } else { // has ssl client cert + CMS.debug("RenewalSubmitter: renewal: has ssl client cert chain"); + // shouldn't expect leaf cert to be always at the + // same location + X509Certificate clientCert = null; + for (int i = 0; i < certs.length; i++) { + clientCert = certs[i]; + byte[] extBytes = clientCert.getExtensionValue("2.5.29.19"); + // try to see if this is a leaf cert + // look for BasicConstraint extension + if (extBytes == null) { + // found leaf cert + CMS.debug("RenewalSubmitter: renewal: found leaf cert"); + break; + } else { + CMS.debug("RenewalSubmitter: renewal: found cert having BasicConstraints ext"); + // it's got BasicConstraints extension + // so it's not likely to be a leaf cert, + // however, check the isCA field regardless + try { + BasicConstraintsExtension bce = + new BasicConstraintsExtension(true, extBytes); + if (bce != null) { + if (!(Boolean) bce.get("is_ca")) { + CMS.debug("RenewalSubmitter: renewal: found CA cert in chain"); + break; + } // else found a ca cert, continue + } + } catch (Exception e) { + CMS.debug("RenewalSubmitter: renewal: exception:" + e.toString()); + return null; + } + } + } + if (clientCert == null) { + CMS.debug("RenewalSubmitter: renewal: no client cert in chain"); + return null; + } + // convert to java X509 cert interface + try { + byte[] certEncoded = clientCert.getEncoded(); + clientCert = new X509CertImpl(certEncoded); + } catch (Exception e) { + e.printStackTrace(); + CMS.debug("RenewalSubmitter: renewal: exception:" + e.toString()); + return null; + } + + certSerial = clientCert.getSerialNumber(); + } + return certSerial; + } + + /* + * fill input info from "request" to context. + * This is expected to be used by renewal where the request + * is retrieved from request record + */ + private void setInputsIntoContext(IRequest request, IProfile profile, IProfileContext ctx, Locale locale) { + // passing inputs into context + Enumeration<String> inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration<String> inputNames = profileInput.getValueNames(); + + while (inputNames.hasMoreElements()) { + String inputName = inputNames.nextElement(); + String inputValue = ""; + CMS.debug("RenewalSubmitter: setInputsIntoContext() getting input name= " + inputName); + try { + inputValue = profileInput.getValue(inputName, locale, request); + } catch (Exception e) { + CMS.debug("RenewalSubmitter: setInputsIntoContext() getvalue() failed: " + e.toString()); + } + + if (inputValue != null) { + CMS.debug("RenewalSubmitter: setInputsIntoContext() setting value in ctx:" + inputValue); + ctx.set(inputName, inputValue); + } else { + CMS.debug("RenewalSubmitter: setInputsIntoContext() value null"); + } + } + } + } + + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/RequestProcessor.java b/base/common/src/com/netscape/cms/servlet/cert/RequestProcessor.java new file mode 100644 index 000000000..9bb0c4b64 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/RequestProcessor.java @@ -0,0 +1,475 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.cert; + +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; + +import javax.servlet.http.HttpServletRequest; + +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzException; +import com.netscape.certsrv.base.BadRequestDataException; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.EPropertyNotFound; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.EDeferException; +import com.netscape.certsrv.profile.EProfileException; +import com.netscape.certsrv.profile.ERejectException; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.profile.IPolicyConstraint; +import com.netscape.certsrv.profile.IPolicyDefault; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileOutput; +import com.netscape.certsrv.profile.IProfilePolicy; +import com.netscape.certsrv.property.EPropertyException; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.profile.common.ProfilePolicy; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.profile.model.PolicyDefault; +import com.netscape.cms.servlet.profile.model.ProfileAttribute; +import com.netscape.cms.servlet.profile.model.ProfileOutput; +import com.netscape.cms.servlet.profile.model.ProfileOutputFactory; +import com.netscape.cms.servlet.profile.model.ProfilePolicySet; +import com.netscape.cms.servlet.request.model.AgentEnrollmentRequestData; +import com.netscape.cms.servlet.request.model.AgentEnrollmentRequestDataFactory; + +public class RequestProcessor extends CertProcessor { + + public RequestProcessor(String id, Locale locale) throws EPropertyNotFound, EBaseException { + super(id, locale); + } + + public AgentEnrollmentRequestData processRequest(CMSRequest cmsReq, IRequest request, String op) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + IRequest ireq = cmsReq.getIRequest(); + + String profileId = ireq.getExtDataInString("profileId"); + IProfile profile = ps.getProfile(profileId); + AgentEnrollmentRequestData data = AgentEnrollmentRequestDataFactory.create(cmsReq, profile, nonces, locale); + + processRequest(req, data, request, op); + return data; + } + + public void processRequest(HttpServletRequest request, AgentEnrollmentRequestData data, IRequest req, String op) + throws EBaseException { + try { + + startTiming("approval"); + + IAuthToken authToken = null; + + if (CMS.debugOn()) { + HashMap<String, String> params = data.toParams(); + printParameterValues(params); + CMS.debug("processRequest op is " + op); + } + + if (authMgr != null) { + authToken = authenticate(request); + } + + AuthzToken authzToken = authorize(aclMethod, authToken, authzResourceName, "approve"); + if (authzToken == null) { + throw new EAuthzException(CMS.getUserMessage(locale, "CMS_AUTHORIZATION_ERROR")); + } + + if (nonces != null) { + String requestNonce = data.getNonce(); + boolean nonceVerified = false; + if (requestNonce != null) { + long nonce = Long.parseLong(requestNonce.trim()); + X509Certificate cert1 = nonces.getCertificate(nonce); + X509Certificate cert2 = getSSLClientCertificate(request); + if (cert1 == null) { + CMS.debug("CertRequestExecutor: Unknown nonce"); + } else if (cert1 != null && cert2 != null && cert1.equals(cert2)) { + nonceVerified = true; + nonces.removeNonce(nonce); + } + } else { + CMS.debug("CertRequestExecutor: Missing nonce"); + } + CMS.debug("CertRequestExecutor: nonceVerified=" + nonceVerified); + if (!nonceVerified) { + CMS.debug("nonce not verified"); + throw new EAuthzException(CMS.getUserMessage(locale, "CMS_AUTHORIZATION_ERROR")); + } + } + + CMS.debug("CertRequestExecutor: processRequest: start serving"); + + RequestId requestId = data.getRequestId(); + if (requestId == null || requestId.equals("")) { + CMS.debug(CMS.getUserMessage(locale, "CMS_REQUEST_ID_NOT_FOUND")); + throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_REQUEST_ID_NOT_FOUND")); + } + CMS.debug("CertRequestExecutor: requestId=" + requestId); + + // check if the request is in one of the terminal states + if (!req.getRequestStatus().equals(RequestStatus.PENDING)) { + CMS.debug(CMS.getUserMessage(locale, "CMS_REQUEST_NOT_PENDING", requestId.toString())); + throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_REQUEST_NOT_PENDING", + requestId.toString())); + } + + // save auth token in request + saveAuthToken(authToken, req); + + String profileId = req.getExtDataInString("profileId"); + if (profileId == null || profileId.equals("")) { + CMS.debug("CertRequestExecutor: Profile Id not found in request"); + throw new EBaseException(CMS.getUserMessage(locale, "CMS_PROFILE_ID_NOT_FOUND")); + } + CMS.debug("CertRequestExecutor: profileId=" + profileId); + + IProfile profile = ps.getProfile(profileId); + if (profile == null) { + CMS.debug(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); + throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); + } + if (!ps.isProfileEnable(profileId)) { + CMS.debug("CertRequestExecutor: Profile " + profileId + " not enabled"); + throw new BadRequestDataException("Profile " + profileId + " not enabled"); + } + + if (op.equals("assign")) { + String owner = req.getRequestOwner(); + + // assigned owner + if (owner != null && owner.length() > 0) { + if (!grantPermission(req, authToken)) { + CMS.debug("CertRequestExecutor: Permission not granted to assign request."); + throw new EAuthzException(CMS.getUserMessage(locale, "CMS_PROFILE_DENY_OPERATION")); + } + } + String id = auditSubjectID(); + req.setRequestOwner(id); + } else { + if (grantPermission(req, authToken)) { + if (op.equals("approve")) { + checkProfileVersion(profile, req); + updateValues(data, req, profile, locale); + updateNotes(data, req); + approveRequest(req, data, profile, locale); + } else if (op.equals("reject")) { + updateNotes(data, req); + rejectRequest(req); + } else if (op.equals("cancel")) { + updateNotes(data, req); + cancelRequest(req); + } else if (op.equals("update")) { + checkProfileVersion(profile, req); + updateValues(data, req, profile, locale); + updateNotes(data, req); + } else if (op.equals("validate")) { + updateValues(data, req, profile, locale); + } else if (op.equals("unassign")) { + req.setRequestOwner(""); + } + } else { + CMS.debug("CertRequestExecutor: Permission not granted to approve/reject/cancel/update/validate/unassign request."); + throw new EAuthzException(CMS.getUserMessage(locale, "CMS_PROFILE_DENY_OPERATION")); + } + } + + // commit request to the storage + if (!op.equals("validate")) { + if (op.equals("approve")) { + queue.markAsServiced(req); + } else { + queue.updateRequest(req); + } + } + endTiming("approval"); + } finally { + endAllEvents(); + } + } + + private boolean grantPermission(IRequest req, IAuthToken token) { + boolean enable = false; + try { + enable = CMS.getConfigStore().getBoolean("request.assignee.enable", false); + } catch (EBaseException e) { + } + + if (!enable) + return true; + String owner = req.getRequestOwner(); + + // unassigned owner + if (owner == null || owner.length() == 0) + return true; + String uid = token.getInString(IAuthToken.USER_ID); + if (uid.equals(owner)) + return true; + + return false; + } + + /** + * Check if the request creation time is older than the profile + * lastModified attribute. + */ + private void checkProfileVersion(IProfile profile, IRequest req) throws EProfileException { + IConfigStore profileConfig = profile.getConfigStore(); + if (profileConfig != null) { + String lastModified = null; + + try { + lastModified = profileConfig.getString("lastModified", ""); + } catch (EBaseException e) { + } + + if (!lastModified.equals("")) { + Date profileModifiedAt = new Date(Long.parseLong(lastModified)); + CMS.debug("CertRequestExecutor: Profile Last Modified=" + + profileModifiedAt); + Date reqCreatedAt = req.getCreationTime(); + CMS.debug("CertRequestExecutor: Request Created At=" + + reqCreatedAt); + if (profileModifiedAt.after(reqCreatedAt)) { + CMS.debug("Profile Newer Than Request"); + throw new ERejectException("Profile Newer Than Request"); + } + } + } + } + + /** + * Cancel request + * <P> + * + * (Certificate Request Processed - a manual "agent" profile based cert cancellation) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + * </ul> + * + * + * @param req the certificate request + * @exception EProfileException an error related to this profile has + * occurred + */ + private void cancelRequest(IRequest req) throws EProfileException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = auditRequesterID(req); + String auditInfoValue = auditInfoValue(req); + + req.setRequestStatus(RequestStatus.CANCELED); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + ILogger.SIGNED_AUDIT_CANCELLATION, + auditInfoValue); + + audit(auditMessage); + } + + /** + * Reject request + * <P> + * + * (Certificate Request Processed - a manual "agent" profile based cert rejection) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + * </ul> + * + * @param req the certificate request + * @exception EProfileException an error related to this profile has + * occurred + */ + private void rejectRequest(IRequest req) throws EProfileException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = auditRequesterID(req); + String auditInfoValue = auditInfoValue(req); + + req.setRequestStatus(RequestStatus.REJECTED); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + ILogger.SIGNED_AUDIT_REJECTION, + auditInfoValue); + + audit(auditMessage); + } + + /** + * Approve request + * <P> + * + * (Certificate Request Processed - a manual "agent" profile based cert acceptance) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + * </ul> + * + * @param request the servlet request + * @param req the certificate request + * @param profile this profile + * @param locale the system locale + * @exception EProfileException an error related to this profile has + * occurred + */ + private void approveRequest(IRequest req, AgentEnrollmentRequestData data, IProfile profile, Locale locale) + throws EProfileException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = auditRequesterID(req); + + try { + profile.execute(req); + req.setRequestStatus(RequestStatus.COMPLETE); + + Enumeration<String> outputIds = profile.getProfileOutputIds(); + while (outputIds.hasMoreElements()) { + IProfileOutput output = profile.getProfileOutput(outputIds.nextElement()); + ProfileOutput addOutput = ProfileOutputFactory.create(output, req, locale); + data.addOutput(addOutput); + } + + // retrieve the certificate + X509CertImpl theCert = req.getExtDataInCert( + IEnrollProfile.REQUEST_ISSUED_CERT); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + ILogger.SIGNED_AUDIT_ACCEPTANCE, + auditInfoCertValue(theCert)); + + audit(auditMessage); + + } catch (EProfileException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + ILogger.SIGNED_AUDIT_ACCEPTANCE, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + + CMS.debug("CertRequestExecutor: about to throw EProfileException because of bad profile execute."); + throw eAudit1; + } + } + + private void updateValues(AgentEnrollmentRequestData data, IRequest req, + IProfile profile, Locale locale) + throws ERejectException, EDeferException, EPropertyException { + + // put request policy defaults in a local hash + HashMap<String, String> policyData = new HashMap<String,String>(); + for (ProfilePolicySet policySet: data.getPolicySets()) { + for (com.netscape.cms.servlet.profile.model.ProfilePolicy policy: policySet.getPolicies()) { + PolicyDefault def = policy.getDef(); + List<ProfileAttribute> attrs = def.getAttributes(); + for (ProfileAttribute attr: attrs) { + policyData.put(attr.getName(), attr.getValue()); + } + } + } + + String profileSetId = req.getExtDataInString("profileSetId"); + + Enumeration<ProfilePolicy> policies = profile.getProfilePolicies(profileSetId); + int count = 0; + + while (policies.hasMoreElements()) { + ProfilePolicy policy = policies.nextElement(); + + setValue(locale, count, policy, req, policyData); + count++; + } + + policies = profile.getProfilePolicies(profileSetId); + count = 0; + while (policies.hasMoreElements()) { + ProfilePolicy policy = policies.nextElement(); + + validate(count, policy, req); + count++; + } + + } + + private void updateNotes(AgentEnrollmentRequestData data, IRequest req) { + String notes = data.getRequestNotes(); + + if (notes != null) { + req.setExtData("requestNotes", notes); + } + } + + private void validate(int count, IProfilePolicy policy, IRequest req) + throws ERejectException, EDeferException { + IPolicyConstraint con = policy.getConstraint(); + + con.validate(req); + } + + private void setValue(Locale locale, int count, IProfilePolicy policy, IRequest req, + HashMap<String, String> data) throws EPropertyException { + // handle default policy + IPolicyDefault def = policy.getDefault(); + Enumeration<String> defNames = def.getValueNames(); + + while (defNames.hasMoreElements()) { + String defName = defNames.nextElement(); + String defValue = data.get(defName); + + def.setValue(defName, locale, req, defValue); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/AuthCredentials.java b/base/common/src/com/netscape/cms/servlet/common/AuthCredentials.java index f01d75c98..32ae0fcc8 100644 --- a/base/common/src/com/netscape/cms/servlet/common/AuthCredentials.java +++ b/base/common/src/com/netscape/cms/servlet/common/AuthCredentials.java @@ -20,8 +20,8 @@ package com.netscape.cms.servlet.common; import java.util.Enumeration; import java.util.Hashtable; +import com.netscape.certsrv.authentication.EAuthException; import com.netscape.certsrv.authentication.IAuthCredentials; -import com.netscape.certsrv.base.EBaseException; import com.netscape.certsrv.base.IArgBlock; /** @@ -52,9 +52,9 @@ public class AuthCredentials implements IAuthCredentials { * @param cred credential * @exception com.netscape.certsrv.base.EBaseException NullPointerException */ - public void set(String name, Object cred) throws EBaseException { + public void set(String name, Object cred) throws EAuthException { if (cred == null) { - throw new EBaseException("AuthCredentials.set()"); + throw new EAuthException("AuthCredentials.set()"); } authCreds.put(name, cred); diff --git a/base/common/src/com/netscape/cms/servlet/common/ServletUtils.java b/base/common/src/com/netscape/cms/servlet/common/ServletUtils.java index 856679e3a..a709b6b02 100644 --- a/base/common/src/com/netscape/cms/servlet/common/ServletUtils.java +++ b/base/common/src/com/netscape/cms/servlet/common/ServletUtils.java @@ -103,4 +103,46 @@ public class ServletUtils { authz.authzMgrAccessInit(aclMethod, acl); } } + + public static String getACLMethod(String aclInfo, String authzMgr, String id) throws EBaseException { + String srcType = AUTHZ_SRC_LDAP; + IAuthzSubsystem authz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ); + + try { + IConfigStore authzConfig = CMS.getConfigStore().getSubStore(AUTHZ_CONFIG_STORE); + srcType = authzConfig.getString(AUTHZ_SRC_TYPE, AUTHZ_SRC_LDAP); + } catch (EBaseException e) { + CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_FAIL_SRC_TYPE")); + } + + String aclMethod = null; + + if (srcType.equalsIgnoreCase(AUTHZ_SRC_XML)) { + CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_INITED", "")); + try { + aclMethod = authzMgr; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + if (aclMethod != null && aclMethod.equalsIgnoreCase(AUTHZ_MGR_BASIC)) { + if (aclInfo != null) { + addACLInfo(authz, aclMethod, aclInfo); + CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_MGR_INIT_DONE", id)); + } else { + CMS.debug(CMS.getLogMessage( + "ADMIN_SRVLT_PROP_ACL_NOT_SPEC", PROP_ACL, id, + AUTHZ_MGR_LDAP)); + } + } else { + CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_PROP_ACL_NOT_SPEC", + PROP_AUTHZ_MGR, id, AUTHZ_MGR_LDAP)); + } + } else { + aclMethod = AUTHZ_MGR_LDAP; + CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_AUTH_LDAP_NOT_XML", id)); + } + + return aclMethod; + } } diff --git a/base/common/src/com/netscape/cms/servlet/processors/Processor.java b/base/common/src/com/netscape/cms/servlet/processors/Processor.java new file mode 100644 index 000000000..d5893a479 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/processors/Processor.java @@ -0,0 +1,1259 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.processors; + +import java.math.BigInteger; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Locale; +import java.util.Map.Entry; +import java.util.StringTokenizer; + +import javax.servlet.http.HttpServletRequest; + +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.IAuthzSubsystem; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.EPropertyNotFound; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.MetaInfo; +import com.netscape.certsrv.base.Nonces; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileAuthenticator; +import com.netscape.certsrv.profile.IProfileSubsystem; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.usrgrp.IGroup; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.certsrv.util.IStatsSubsystem; +import com.netscape.cms.servlet.common.AuthCredentials; +import com.netscape.cms.servlet.common.CMSGateway; +import com.netscape.cms.servlet.common.ServletUtils; +import com.netscape.cmsutil.util.Utils; + +public class Processor { + + public final static String ARG_AUTH_TOKEN = "auth_token"; + public final static String ARG_REQUEST_OWNER = "requestOwner"; + public final static String HDR_LANG = "accept-language"; + public final static String ARG_PROFILE = "profile"; + public final static String ARG_REQUEST_NOTES = "requestNotes"; + public final static String ARG_PROFILE_ID = "profileId"; + public final static String ARG_RENEWAL_PROFILE_ID = "rprofileId"; + public final static String ARG_PROFILE_IS_ENABLED = "profileIsEnable"; + public final static String ARG_PROFILE_IS_VISIBLE = "profileIsVisible"; + public final static String ARG_PROFILE_ENABLED_BY = "profileEnableBy"; + public final static String ARG_PROFILE_APPROVED_BY = "profileApprovedBy"; + public final static String ARG_PROFILE_NAME = "profileName"; + public final static String ARG_PROFILE_DESC = "profileDesc"; + public final static String ARG_PROFILE_REMOTE_HOST = "profileRemoteHost"; + public final static String ARG_PROFILE_REMOTE_ADDR = "profileRemoteAddr"; + public final static String ARG_PROFILE_SET_ID = "profileSetId"; + public final static String ARG_OUTPUT_LIST = "outputList"; + public final static String ARG_OUTPUT_ID = "outputId"; + public final static String ARG_OUTPUT_SYNTAX = "outputSyntax"; + public final static String ARG_OUTPUT_CONSTRAINT = "outputConstraint"; + public final static String ARG_OUTPUT_NAME = "outputName"; + public final static String ARG_OUTPUT_VAL = "outputVal"; + public final static String ARG_REQUEST_LIST = "requestList"; + public final static String ARG_REQUEST_ID = "requestId"; + public final static String ARG_REQUEST_TYPE = "requestType"; + public final static String ARG_REQUEST_STATUS = "requestStatus"; + public final static String ARG_REQUEST_CREATION_TIME = "requestCreationTime"; + public final static String ARG_REQUEST_MODIFICATION_TIME = "requestModificationTime"; + public final static String ARG_REQUEST_NONCE = "nonce"; + public final static String ARG_OP = "op"; + public final static String ARG_REQUESTS = "requests"; + public final static String ARG_ERROR_CODE = "errorCode"; + public final static String ARG_ERROR_REASON = "errorReason"; + public final static String CERT_ATTR = "javax.servlet.request.X509Certificate"; + + // servlet config constants + public static final String PROFILE_ID = "profileId"; + public static final String AUTH_ID = "authId"; + public static final String ACL_METHOD = "aclMethod"; + public static final String AUTHZ_RESOURCE_NAME = "authzResourceName"; + public static final String AUTH_MGR = "authMgr"; + public static final String AUTHZ_MGR = "authzMgr"; + public static final String GET_CLIENT_CERT = "getClientCert"; + public static final String ACL_INFO = "ACLinfo"; + public static final String AUTHORITY_ID = "authorityId"; + public static final String PROFILE_SUB_ID = "profileSubId"; + + public final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5"; + public final static String LOGGING_SIGNED_AUDIT_AUTH_FAIL = + "LOGGING_SIGNED_AUDIT_AUTH_FAIL_4"; + public final static String LOGGING_SIGNED_AUDIT_AUTH_SUCCESS = + "LOGGING_SIGNED_AUDIT_AUTH_SUCCESS_3"; + public final static String LOGGING_SIGNED_AUDIT_AUTHZ_FAIL = + "LOGGING_SIGNED_AUDIT_AUTHZ_FAIL_4"; + public final static String LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS = + "LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS_4"; + public final static String LOGGING_SIGNED_AUDIT_ROLE_ASSUME = + "LOGGING_SIGNED_AUDIT_ROLE_ASSUME_3"; + public final static String SIGNED_AUDIT_CERT_REQUEST_REASON = + "requestNotes"; + + protected String profileID; + protected String profileSubId; + protected String aclMethod; + protected String authzResourceName; + protected String authMgr; + protected String getClientCert = "false"; + protected Nonces nonces; + protected Locale locale; + + // subsystems + protected ICertificateAuthority authority = (ICertificateAuthority) CMS.getSubsystem("ca"); + protected IAuthzSubsystem authz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ); + protected IUGSubsystem ug = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG); + protected IRequestQueue queue; + protected IProfileSubsystem ps; + protected ICertificateRepository certdb; + + //logging and stats + protected ILogger signedAuditLogger = CMS.getSignedAuditLogger(); + protected LinkedHashSet<String> statEvents = new LinkedHashSet<String>(); + + public Processor(String id, Locale locale) throws EPropertyNotFound, EBaseException { + IConfigStore cs = CMS.getConfigStore().getSubStore("profile." + id); + this.locale = locale; + this.profileID = cs.getString(PROFILE_ID, "").isEmpty() ? null : cs.getString(PROFILE_ID); + this.authzResourceName = cs.getString(AUTHZ_RESOURCE_NAME, "").isEmpty() ? null : + cs.getString(AUTHZ_RESOURCE_NAME); + this.authMgr = cs.getString(AUTH_MGR, "").isEmpty() ? null : cs.getString(AUTH_MGR); + this.getClientCert = cs.getString(GET_CLIENT_CERT, "").isEmpty() ? "false" : cs.getString(GET_CLIENT_CERT); + this.profileSubId = cs.getString(PROFILE_SUB_ID, "").isEmpty() ? IProfileSubsystem.ID : + cs.getString(PROFILE_SUB_ID); + + String aclInfo = cs.getString(ACL_INFO, "").isEmpty() ? null : cs.getString(ACL_INFO); + String authzMgr = cs.getString(AUTHZ_MGR, "").isEmpty() ? null : cs.getString(AUTHZ_MGR); + this.aclMethod = ServletUtils.getACLMethod(aclInfo, authzMgr, id); + + // currently unused but in servlet config + // authId = cs.getString(AUTH_ID, "").isEmpty() ? null : cs.getString(AUTH_ID); + + if (authority == null) { + throw new EBaseException("CertProcessor: authority is null"); + } + + if (authority.noncesEnabled()) { + nonces = authority.getNonces(); + } + + queue = authority.getRequestQueue(); + if (queue == null) { + throw new EBaseException("CertProcessor: cannot get request queue"); + } + + if (profileSubId == null || profileSubId.equals("")) { + profileSubId = IProfileSubsystem.ID; + } + + ps = (IProfileSubsystem) CMS.getSubsystem(profileSubId); + if (ps == null) { + throw new EBaseException("CertProcessor: Profile Subsystem not found"); + } + + certdb = authority.getCertificateRepository(); + if (certdb == null) { + throw new EBaseException("CertProcessor: Certificate repository not found"); + } + } + + /****************************************** + * Stats - to be moved to Stats module + ******************************************/ + + public void startTiming(String event) { + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.startTiming(event, true); + } + statEvents.add(event); + } + + public void endTiming(String event) { + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.endTiming(event); + } + statEvents.remove(event); + } + + public void endAllEvents() { + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + Iterator<String> iter = statEvents.iterator(); + while (iter.hasNext()) { + String event = iter.next(); + statsSub.endTiming(event); + iter.remove(); + } + } + } + + /****************************************** + * Utility Functions + ******************************************/ + + public IRequest getRequest(String rid) throws EBaseException { + IRequest request = queue.findRequest(new RequestId(rid)); + return request; + } + + protected IRequest getOriginalRequest(BigInteger certSerial, ICertRecord rec) throws EBaseException { + MetaInfo metaInfo = (MetaInfo) rec.get(ICertRecord.ATTR_META_INFO); + if (metaInfo == null) { + CMS.debug("getOriginalRequest: cert record locating MetaInfo failed for serial number " + + certSerial.toString()); + return null; + } + + String rid = (String) metaInfo.get(ICertRecord.META_REQUEST_ID); + if (rid == null) { + CMS.debug("getOriginalRequest: cert record locating request id in MetaInfo failed " + + "for serial number " + certSerial.toString()); + return null; + } + + IRequest request = queue.findRequest(new RequestId(rid)); + return request; + } + + protected void printParameterValues(HashMap<String, String> data) { + CMS.debug("Start of CertProcessor Input Parameters"); + + for (Entry<String, String> entry : data.entrySet()) { + String paramName = entry.getKey(); + // added this facility so that password can be hidden, + // all sensitive parameters should be prefixed with + // __ (double underscores); however, in the event that + // a security parameter slips through, we perform multiple + // additional checks to insure that it is NOT displayed + if (paramName.startsWith("__") || + paramName.endsWith("password") || + paramName.endsWith("passwd") || + paramName.endsWith("pwd") || + paramName.equalsIgnoreCase("admin_password_again") || + paramName.equalsIgnoreCase("directoryManagerPwd") || + paramName.equalsIgnoreCase("bindpassword") || + paramName.equalsIgnoreCase("bindpwd") || + paramName.equalsIgnoreCase("passwd") || + paramName.equalsIgnoreCase("password") || + paramName.equalsIgnoreCase("pin") || + paramName.equalsIgnoreCase("pwd") || + paramName.equalsIgnoreCase("pwdagain") || + paramName.equalsIgnoreCase("uPasswd")) { + CMS.debug("CertProcessor Input Parameter " + paramName + "='(sensitive)'"); + } else { + CMS.debug("CertProcessor Input Parameter " + paramName + "='" + entry.getValue() + "'"); + } + } + + CMS.debug("End of CertProcessor Input Parameters"); + } + + protected StringBuffer escapeValueRfc1779(String v, boolean doubleEscape) { + StringBuffer result = new StringBuffer(); + + // Do we need to escape any characters + for (int i = 0; i < v.length(); i++) { + int c = v.charAt(i); + if (c == ',' || c == '=' || c == '+' || c == '<' || + c == '>' || c == '#' || c == ';' || c == '\r' || + c == '\n' || c == '\\' || c == '"') { + if ((c == 0x5c) && ((i + 1) < v.length())) { + int nextC = v.charAt(i + 1); + if ((c == 0x5c) && (nextC == ',' || nextC == '=' || nextC == '+' || + nextC == '<' || nextC == '>' || nextC == '#' || + nextC == ';' || nextC == '\r' || nextC == '\n' || + nextC == '\\' || nextC == '"')) { + if (doubleEscape) + result.append('\\'); + } else { + result.append('\\'); + if (doubleEscape) + result.append('\\'); + } + } else { + result.append('\\'); + if (doubleEscape) + result.append('\\'); + } + } + if (c == '\r') { + result.append("0D"); + } else if (c == '\n') { + result.append("0A"); + } else { + result.append((char) c); + } + } + return result; + } + + /** + * get ssl client authenticated certificate + */ + public static X509Certificate getSSLClientCertificate(HttpServletRequest httpReq) + throws EBaseException { + X509Certificate cert = null; + + CMS.debug(CMS.getLogMessage("CMSGW_GETTING_SSL_CLIENT_CERT")); + + // iws60 support Java Servlet Spec V2.2, attribute + // javax.servlet.request.X509Certificate now contains array + // of X509Certificates instead of one X509Certificate object + X509Certificate[] allCerts = (X509Certificate[]) httpReq.getAttribute(CERT_ATTR); + + if (allCerts == null || allCerts.length == 0) { + throw new EBaseException("You did not provide a valid certificate for this operation"); + } + + cert = allCerts[0]; + + if (cert == null) { + // just don't have a cert. + CMS.debug(CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL")); + return null; + } + + // convert to sun's x509 cert interface. + try { + byte[] certEncoded = cert.getEncoded(); + cert = new X509CertImpl(certEncoded); + } catch (CertificateEncodingException e) { + CMS.debug(CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL_ENCODE", e.getMessage())); + return null; + } catch (CertificateException e) { + CMS.debug(CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL_DECODE", e.getMessage())); + return null; + } + return cert; + } + + protected static Hashtable<String, String> toHashtable(HttpServletRequest req) { + Hashtable<String, String> httpReqHash = new Hashtable<String, String>(); + Enumeration<?> names = req.getParameterNames(); + + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + + httpReqHash.put(name, req.getParameter(name)); + } + return httpReqHash; + } + + /****************************************** + * AUTHENTICATION FUNCTIONS (move to Realm?) + ******************************************/ + + /* + * authenticate for renewal - more to add necessary params/values + * to the session context + */ + public IAuthToken authenticate(IProfileAuthenticator authenticator, + HttpServletRequest request, IRequest origReq, SessionContext context) throws EBaseException + { + IAuthToken authToken = authenticate(authenticator, request); + // For renewal, fill in necessary params + if (authToken != null) { + String ouid = origReq.getExtDataInString("auth_token.uid"); + // if the orig cert was manually approved, then there was + // no auth token uid. Try to get the uid from the cert dn + // itself, if possible + if (ouid == null) { + String sdn = (String) context.get("origSubjectDN"); + if (sdn != null) { + ouid = getUidFromDN(sdn); + if (ouid != null) + CMS.debug("CertProcessor: renewal: authToken original uid not found"); + } + } else { + CMS.debug("CertProcessor: renewal: authToken original uid found in orig request auth_token"); + } + String auid = authToken.getInString("uid"); + if (auid != null) { // not through ssl client auth + CMS.debug("CertProcessor: renewal: authToken uid found:" + auid); + // authenticated with uid + // put "orig_req.auth_token.uid" so that authz with + // UserOrigReqAccessEvaluator will work + if (ouid != null) { + context.put("orig_req.auth_token.uid", ouid); + CMS.debug("CertProcessor: renewal: authToken original uid found:" + ouid); + } else { + CMS.debug("CertProcessor: renewal: authToken original uid not found"); + } + } else { // through ssl client auth? + CMS.debug("CertProcessor: renewal: authToken uid not found:"); + // put in orig_req's uid + if (ouid != null) { + CMS.debug("CertProcessor: renewal: origReq uid not null:" + ouid + ". Setting authtoken"); + authToken.set("uid", ouid); + context.put(SessionContext.USER_ID, ouid); + } else { + CMS.debug("CertProcessor: renewal: origReq uid not found"); + // throw new EBaseException("origReq uid not found"); + } + } + + String userdn = origReq.getExtDataInString("auth_token.userdn"); + if (userdn != null) { + CMS.debug("CertProcessor: renewal: origReq userdn not null:" + userdn + ". Setting authtoken"); + authToken.set("userdn", userdn); + } else { + CMS.debug("CertProcessor: renewal: origReq userdn not found"); + // throw new EBaseException("origReq userdn not found"); + } + } else { + CMS.debug("CertProcessor: renewal: authToken null"); + } + return authToken; + } + + public IAuthToken authenticate(IProfileAuthenticator authenticator, + HttpServletRequest request) throws EBaseException { + AuthCredentials credentials = new AuthCredentials(); + + // build credential + Enumeration<String> authNames = authenticator.getValueNames(); + + if (authNames != null) { + while (authNames.hasMoreElements()) { + String authName = authNames.nextElement(); + + credentials.set(authName, request.getParameter(authName)); + } + } + + credentials.set("clientHost", request.getRemoteHost()); + IAuthToken authToken = authenticator.authenticate(credentials); + + SessionContext sc = SessionContext.getContext(); + if (sc != null) { + sc.put(SessionContext.AUTH_MANAGER_ID, authenticator.getName()); + String userid = authToken.getInString(IAuthToken.USER_ID); + if (userid != null) { + sc.put(SessionContext.USER_ID, userid); + } + } + + return authToken; + } + + public IAuthToken authenticate(HttpServletRequest request, IRequest origReq, IProfileAuthenticator authenticator, + SessionContext context, boolean isRenewal) throws EBaseException { + startTiming("profile_authentication"); + + IAuthToken authToken = null; + if (authenticator != null) { + CMS.debug("authenticate: authentication required."); + String uid_cred = "Unidentified"; + String uid_attempted_cred = "Unidentified"; + Enumeration<String> authIds = authenticator.getValueNames(); + //Attempt to possibly fetch attempted uid, may not always be available. + if (authIds != null) { + while (authIds.hasMoreElements()) { + String authName = authIds.nextElement(); + String value = request.getParameter(authName); + if (value != null) { + if (authName.equals("uid")) { + uid_attempted_cred = value; + } + } + } + } + + String authSubjectID = auditSubjectID(); + String authMgrID = authenticator.getName(); + String auditMessage = null; + try { + if (isRenewal) { + authToken = authenticate(authenticator, request, origReq, context); + } else { + authToken = authenticate(authenticator, request); + } + } catch (EBaseException e) { + CMS.debug("CertProcessor: authentication error " + e.toString()); + + authSubjectID += " : " + uid_cred; + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + authSubjectID, + ILogger.FAILURE, + authMgrID, + uid_attempted_cred); + audit(auditMessage); + + throw e; + } + + //Log successful authentication + //Attempt to get uid from authToken, most tokens respond to the "uid" cred. + uid_cred = authToken.getInString("uid"); + + if (uid_cred == null || uid_cred.length() == 0) { + uid_cred = "Unidentified"; + } + + authSubjectID = authSubjectID + " : " + uid_cred; + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_SUCCESS, + authSubjectID, + ILogger.SUCCESS, + authMgrID); + + audit(auditMessage); + } + endTiming("profile_authentication"); + return authToken; + } + + public IAuthToken authenticate(HttpServletRequest httpReq) + throws EBaseException { + return authenticate(httpReq, authMgr); + } + + public static void saveAuthToken(IAuthToken token, IRequest req) { + if (token != null && req != null) + req.setExtData(IRequest.AUTH_TOKEN, token); + + // # 56230 - expose auth token parameters to the policy predicate + if (token != null && req != null) { + Enumeration<String> e = token.getElements(); + while (e.hasMoreElements()) { + String n = e.nextElement(); + String[] x1 = token.getInStringArray(n); + if (x1 != null) { + for (int i = 0; i < x1.length; i++) { + CMS.debug("Setting " + IRequest.AUTH_TOKEN + "-" + n + + "(" + i + ")=" + x1[i]); + req.setExtData(IRequest.AUTH_TOKEN + "-" + n + "(" + i + ")", + x1[i]); + } + } else { + String x = token.getInString(n); + if (x != null) { + CMS.debug("Setting " + IRequest.AUTH_TOKEN + "-" + n + "=" + x); + req.setExtData(IRequest.AUTH_TOKEN + "-" + n, x); + } + } + } // while + } // if + } + + public IAuthToken authenticate(HttpServletRequest httpReq, String authMgrName) + throws EBaseException { + String auditMessage = null; + String auditSubjectID = ILogger.UNIDENTIFIED; + String auditAuthMgrID = ILogger.UNIDENTIFIED; + String auditUID = ILogger.UNIDENTIFIED; + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + IArgBlock httpArgs = CMS.createArgBlock(toHashtable(httpReq)); + SessionContext ctx = SessionContext.getContext(); + String ip = httpReq.getRemoteAddr(); + CMS.debug("IP: " + ip); + + if (ip != null) { + ctx.put(SessionContext.IPADDRESS, ip); + } + if (authMgrName != null) { + CMS.debug("AuthMgrName: " + authMgrName); + ctx.put(SessionContext.AUTH_MANAGER_ID, authMgrName); + } + // put locale into session context + ctx.put(SessionContext.LOCALE, locale); + + // + // check ssl client authentication if specified. + // + X509Certificate clientCert = null; + + if (getClientCert != null && getClientCert.equals("true")) { + CMS.debug("CMSServlet: retrieving SSL certificate"); + clientCert = getSSLClientCertificate(httpReq); + } + + // + // check authentication by auth manager if any. + // + if (authMgrName == null) { + + // Fixed Blackflag Bug #613900: Since this code block does + // NOT actually constitute an authentication failure, but + // rather the case in which a given servlet has been correctly + // configured to NOT require an authentication manager, the + // audit message called LOGGING_SIGNED_AUDIT_AUTH_FAIL has + // been removed. + + CMS.debug("CMSServlet: no authMgrName"); + return null; + } else { + // save the "Subject DN" of this certificate in case it + // must be audited as an authentication failure + if (clientCert == null) { + CMS.debug("CMSServlet: no client certificate found"); + } else { + String certUID = clientCert.getSubjectDN().getName(); + CMS.debug("CMSServlet: certUID=" + certUID); + + if (certUID != null) { + certUID = certUID.trim(); + + if (!(certUID.equals(""))) { + // reset the "auditUID" + auditUID = certUID; + } + } + } + + // reset the "auditAuthMgrID" + auditAuthMgrID = authMgrName; + } + AuthToken authToken = CMSGateway.checkAuthManager(httpReq, + httpArgs, + clientCert, + authMgrName); + if (authToken == null) { + return null; + } + String userid = authToken.getInString(IAuthToken.USER_ID); + + CMS.debug("CMSServlet: userid=" + userid); + + if (userid != null) { + ctx.put(SessionContext.USER_ID, userid); + } + + // reset the "auditSubjectID" + auditSubjectID = auditSubjectID(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditAuthMgrID); + + audit(auditMessage); + + return authToken; + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditAuthMgrID, + auditUID); + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } + } + + String getUidFromDN(String userdn) { + StringTokenizer st = new StringTokenizer(userdn, ","); + while (st.hasMoreTokens()) { + String t = st.nextToken(); + int i = t.indexOf("="); + + if (i == -1) { + continue; + } + String n = t.substring(0, i); + if (n.equalsIgnoreCase("uid")) { + String v = t.substring(i + 1); + CMS.debug("CertProcessor:: getUidFromDN(): uid found:" + v); + return v; + } else { + continue; + } + } + return null; + } + + /****************************************** + * AUTHZ FNCTIONS (to be moved to Realm?) + *****************************************/ + + public AuthzToken authorize(String authzMgrName, String resource, IAuthToken authToken, + String exp) throws EBaseException { + AuthzToken authzToken = null; + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditGroupID = auditGroupID(); + String auditACLResource = resource; + String auditOperation = "enroll"; + + try { + authzToken = authz.authorize(authzMgrName, authToken, exp); + if (authzToken != null) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditSubjectID, + ILogger.SUCCESS, + auditGroupID); + + audit(auditMessage); + } else { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditSubjectID, + ILogger.FAILURE, + auditGroupID); + + audit(auditMessage); + } + return authzToken; + } catch (EBaseException e) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditSubjectID, + ILogger.FAILURE, + auditGroupID); + + audit(auditMessage); + throw e; + } + } + + /** + * Authorize must occur after Authenticate + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_FAIL used when authorization has failed + * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS used when authorization is successful + * <li>signed.audit LOGGING_SIGNED_AUDIT_ROLE_ASSUME used when user assumes a role (in current CS that's when one + * accesses a role port) + * </ul> + * + * @param authzMgrName string representing the name of the authorization + * manager + * @param authToken the authentication token + * @param resource a string representing the ACL resource id as defined in + * the ACL resource list + * @param operation a string representing one of the operations as defined + * within the ACL statement (e. g. - "read" for an ACL statement containing + * "(read,write)") + * @exception EBaseException an error has occurred + * @return the authorization token + */ + public AuthzToken authorize(String authzMgrName, IAuthToken authToken, + String resource, String operation) { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditGroupID = auditGroupID(); + String auditID = auditSubjectID; + String auditACLResource = resource; + String auditOperation = operation; + + SessionContext auditContext = SessionContext.getExistingContext(); + String authManagerId = null; + + if (auditContext != null) { + authManagerId = (String) auditContext.get(SessionContext.AUTH_MANAGER_ID); + + if (authManagerId != null && authManagerId.equals("TokenAuth")) { + if (auditSubjectID.equals(ILogger.NONROLEUSER) || + auditSubjectID.equals(ILogger.UNIDENTIFIED)) { + CMS.debug("CMSServlet: in authorize... TokenAuth auditSubjectID unavailable, changing to auditGroupID"); + auditID = auditGroupID; + } + } + } + + // "normalize" the "auditACLResource" value + if (auditACLResource != null) { + auditACLResource = auditACLResource.trim(); + } + + // "normalize" the "auditOperation" value + if (auditOperation != null) { + auditOperation = auditOperation.trim(); + } + + if (authzMgrName == null) { + // Fixed Blackflag Bug #613900: Since this code block does + // NOT actually constitute an authorization failure, but + // rather the case in which a given servlet has been correctly + // configured to NOT require an authorization manager, the + // audit message called LOGGING_SIGNED_AUDIT_AUTHZ_FAIL and + // the audit message called LOGGING_SIGNED_AUDIT_ROLE_ASSUME + // (marked as a failure) have been removed. + + return null; + } + + try { + AuthzToken authzTok = authz.authorize(authzMgrName, + authToken, + resource, + operation); + + if (authzTok != null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditID, + ILogger.SUCCESS, + auditGroups(auditSubjectID)); + + audit(auditMessage); + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditID, + ILogger.FAILURE, + auditGroups(auditSubjectID)); + + audit(auditMessage); + } + + return authzTok; + } catch (Exception eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditID, + ILogger.FAILURE, + auditGroups(auditSubjectID)); + + audit(auditMessage); + + return null; + } + } + + public void authorize(String profileId, IProfile profile, IAuthToken authToken) throws EBaseException { + if (authToken != null) { + CMS.debug("CertProcessor authToken not null"); + + String acl = profile.getAuthzAcl(); + CMS.debug("CertProcessor: authz using acl: " + acl); + if (acl != null && acl.length() > 0) { + String resource = profileId + ".authz.acl"; + authorize(aclMethod, resource, authToken, acl); + } + } + } + + /****************************************** + * AUDIT FUNCTIONS (to be moved to Auditor?) + ******************************************/ + protected void audit(String msg) { + // in this case, do NOT strip preceding/trailing whitespace + // from passed-in String parameters + + if (signedAuditLogger == null) { + return; + } + + signedAuditLogger.log(ILogger.EV_SIGNED_AUDIT, + null, + ILogger.S_SIGNED_AUDIT, + ILogger.LL_SECURITY, + msg); + } + + /** + * Signed Audit Log Requester ID + * + * This method is called to obtain the "RequesterID" for + * a signed audit log message. + * <P> + * + * @param request the actual request + * @return id string containing the signed audit log message RequesterID + */ + protected String auditRequesterID(IRequest request) { + // if no signed audit object exists, bail + if (signedAuditLogger == null) { + return null; + } + + String requesterID = ILogger.UNIDENTIFIED; + + if (request != null) { + // overwrite "requesterID" if and only if "id" != null + String id = request.getRequestId().toString(); + + if (id != null) { + requesterID = id.trim(); + } + } + + return requesterID; + } + + /** + * Signed Audit Log Info Certificate Value + * + * This method is called to obtain the certificate from the passed in + * "X509CertImpl" for a signed audit log message. + * <P> + * + * @param request request containing an X509CertImpl + * @return cert string containing the certificate + */ + protected String auditInfoCertValue(IRequest request) { + // if no signed audit object exists, bail + if (signedAuditLogger == null) { + return null; + } + + X509CertImpl x509cert = request.getExtDataInCert( + IEnrollProfile.REQUEST_ISSUED_CERT); + + if (x509cert == null) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + byte rawData[] = null; + + try { + rawData = x509cert.getEncoded(); + } catch (CertificateEncodingException e) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + String cert = null; + + // convert "rawData" into "base64Data" + if (rawData != null) { + String base64Data = null; + + base64Data = Utils.base64encode(rawData).trim(); + + // extract all line separators from the "base64Data" + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < base64Data.length(); i++) { + if (!Character.isWhitespace(base64Data.charAt(i))) { + sb.append(base64Data.charAt(i)); + + } + } + cert = sb.toString(); + } + + if (cert != null) { + cert = cert.trim(); + + if (cert.equals("")) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } else { + return cert; + } + } else { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } + + protected String auditSubjectID() { + // if no signed audit object exists, bail + if (signedAuditLogger == null) { + return null; + } + + CMS.debug("CMSServlet: in auditSubjectID"); + String subjectID = null; + + // Initialize subjectID + SessionContext auditContext = SessionContext.getExistingContext(); + + CMS.debug("CMSServlet: auditSubjectID auditContext " + auditContext); + if (auditContext != null) { + subjectID = (String) + auditContext.get(SessionContext.USER_ID); + + CMS.debug("CMSServlet auditSubjectID: subjectID: " + subjectID); + if (subjectID != null) { + subjectID = subjectID.trim(); + } else { + subjectID = ILogger.NONROLEUSER; + } + } else { + subjectID = ILogger.UNIDENTIFIED; + } + + return subjectID; + } + + protected String auditGroupID() { + // if no signed audit object exists, bail + if (signedAuditLogger == null) { + return null; + } + + CMS.debug("CMSServlet: in auditGroupID"); + String groupID = null; + + // Initialize groupID + SessionContext auditContext = SessionContext.getExistingContext(); + + CMS.debug("CMSServlet: auditGroupID auditContext " + auditContext); + if (auditContext != null) { + groupID = (String) + auditContext.get(SessionContext.GROUP_ID); + + CMS.debug("CMSServlet auditGroupID: groupID: " + groupID); + if (groupID != null) { + groupID = groupID.trim(); + } else { + groupID = ILogger.NONROLEUSER; + } + } else { + groupID = ILogger.UNIDENTIFIED; + } + + return groupID; + } + + /** + * Signed Audit Log Info Value + * + * This method is called to obtain the "reason" for + * a signed audit log message. + * <P> + * + * @param request the actual request + * @return reason string containing the signed audit log message reason + */ + protected String auditInfoValue(IRequest request) { + // if no signed audit object exists, bail + if (signedAuditLogger == null) { + return null; + } + + String reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + + if (request != null) { + // overwrite "reason" if and only if "info" != null + String info = + request.getExtDataInString(SIGNED_AUDIT_CERT_REQUEST_REASON); + + if (info != null) { + reason = info.trim(); + + // overwrite "reason" if and only if "reason" is empty + if (reason.equals("")) { + reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } + } + + return reason; + } + + /** + * Signed Audit Log Info Certificate Value + * + * This method is called to obtain the certificate from the passed in + * "X509CertImpl" for a signed audit log message. + * <P> + * + * @param x509cert an X509CertImpl + * @return cert string containing the certificate + */ + protected String auditInfoCertValue(X509CertImpl x509cert) { + // if no signed audit object exists, bail + if (signedAuditLogger == null) { + return null; + } + + if (x509cert == null) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + byte rawData[] = null; + + try { + rawData = x509cert.getEncoded(); + } catch (CertificateEncodingException e) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + String cert = null; + + // convert "rawData" into "base64Data" + if (rawData != null) { + String base64Data = null; + + base64Data = Utils.base64encode(rawData).trim(); + + // extract all line separators from the "base64Data" + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < base64Data.length(); i++) { + if (!Character.isWhitespace(base64Data.charAt(i))) { + sb.append(base64Data.charAt(i)); + } + } + cert = sb.toString(); + } + + if (cert != null) { + cert = cert.trim(); + + if (cert.equals("")) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } else { + return cert; + } + } else { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } + + /** + * Signed Audit Groups + * + * This method is called to extract all "groups" associated + * with the "auditSubjectID()". + * <P> + * + * @param SubjectID string containing the signed audit log message SubjectID + * @return a delimited string of groups associated + * with the "auditSubjectID()" + */ + protected String auditGroups(String SubjectID) { + // if no signed audit object exists, bail + if (signedAuditLogger == null) { + return null; + } + + if ((SubjectID == null) || + (SubjectID.equals(ILogger.UNIDENTIFIED))) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + Enumeration<IGroup> groups = null; + + try { + groups = ug.findGroups("*"); + } catch (Exception e) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + StringBuffer membersString = new StringBuffer(); + + while (groups.hasMoreElements()) { + IGroup group = groups.nextElement(); + + if (group.isMember(SubjectID) == true) { + if (membersString.length() != 0) { + membersString.append(", "); + } + + membersString.append(group.getGroupID()); + } + } + + if (membersString.length() != 0) { + return membersString.toString(); + } else { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java index 996b65d78..0f9f34144 100644 --- a/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java +++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java @@ -17,52 +17,33 @@ // --- END COPYRIGHT BLOCK --- package com.netscape.cms.servlet.profile; -import java.security.cert.CertificateEncodingException; -import java.security.cert.X509Certificate; -import java.util.Date; -import java.util.Enumeration; import java.util.Locale; import javax.servlet.ServletConfig; import javax.servlet.ServletException; -import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import netscape.security.x509.X509CertImpl; - import com.netscape.certsrv.apps.CMS; -import com.netscape.certsrv.authentication.IAuthToken; -import com.netscape.certsrv.authority.IAuthority; -import com.netscape.certsrv.authorization.AuthzToken; -import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.authentication.EAuthException; +import com.netscape.certsrv.authorization.EAuthzException; +import com.netscape.certsrv.base.BadRequestDataException; import com.netscape.certsrv.base.EBaseException; -import com.netscape.certsrv.base.IConfigStore; -import com.netscape.certsrv.base.Nonces; -import com.netscape.certsrv.ca.ICertificateAuthority; import com.netscape.certsrv.logging.ILogger; import com.netscape.certsrv.profile.EDeferException; import com.netscape.certsrv.profile.EProfileException; import com.netscape.certsrv.profile.ERejectException; -import com.netscape.certsrv.profile.IEnrollProfile; -import com.netscape.certsrv.profile.IPolicyConstraint; -import com.netscape.certsrv.profile.IPolicyDefault; -import com.netscape.certsrv.profile.IProfile; -import com.netscape.certsrv.profile.IProfileOutput; -import com.netscape.certsrv.profile.IProfilePolicy; -import com.netscape.certsrv.profile.IProfileSubsystem; +import com.netscape.certsrv.property.Descriptor; import com.netscape.certsrv.property.EPropertyException; -import com.netscape.certsrv.property.IDescriptor; 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.template.ArgList; import com.netscape.certsrv.template.ArgSet; -import com.netscape.certsrv.util.IStatsSubsystem; -import com.netscape.cms.profile.common.ProfilePolicy; +import com.netscape.certsrv.template.ArgString; +import com.netscape.cms.servlet.cert.RequestProcessor; import com.netscape.cms.servlet.common.CMSRequest; -import com.netscape.cmsutil.util.Utils; +import com.netscape.cms.servlet.profile.model.ProfileAttribute; +import com.netscape.cms.servlet.profile.model.ProfileOutput; +import com.netscape.cms.servlet.request.model.AgentEnrollmentRequestData; /** * This servlet approves profile-based request. @@ -70,400 +51,91 @@ import com.netscape.cmsutil.util.Utils; * @version $Revision$, $Date$ */ public class ProfileProcessServlet extends ProfileServlet { - /** - * - */ - private static final long serialVersionUID = 5244627530516577838L; - private static final String PROP_AUTHORITY_ID = "authorityId"; - private String mAuthorityId = null; - private Nonces mNonces = null; - private final static String SIGNED_AUDIT_CERT_REQUEST_REASON = - "requestNotes"; - private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED = - "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5"; + private static final long serialVersionUID = 5244627530516577838L; public ProfileProcessServlet() { } public void init(ServletConfig sc) throws ServletException { super.init(sc); - mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID); - - ICertificateAuthority authority = null; - if (mAuthorityId != null) - authority = (ICertificateAuthority) CMS.getSubsystem(mAuthorityId); - - if (authority != null && authority.noncesEnabled()) { - mNonces = authority.getNonces(); - } } public void process(CMSRequest cmsReq) throws EBaseException { HttpServletRequest request = cmsReq.getHttpReq(); HttpServletResponse response = cmsReq.getHttpResp(); - IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); - if (statsSub != null) { - statsSub.startTiming("approval", true /* main action */); - } - - IAuthToken authToken = null; - ArgSet args = new ArgSet(); - Locale locale = getLocale(request); + ArgSet args = new ArgSet(); + args.set(ARG_ERROR_CODE, "0"); + args.set(ARG_ERROR_REASON, ""); - if (mAuthMgr != null) { - try { - authToken = authenticate(cmsReq); - } catch (EBaseException e) { - CMS.debug("ProfileProcessServlet: " + e.toString()); - log(ILogger.LL_FAILURE, - CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_AUTHENTICATION_ERROR")); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } - return; - } - } - - AuthzToken authzToken = null; - - try { - authzToken = authorize(mAclMethod, authToken, - mAuthzResourceName, "approve"); - } 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) { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_AUTHORIZATION_ERROR")); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } - return; - } - - if (mNonces != null) { - String requestNonce = request.getParameter(ARG_REQUEST_NONCE); - boolean nonceVerified = false; - if (requestNonce != null) { - long nonce = Long.parseLong(requestNonce.trim()); - X509Certificate cert1 = mNonces.getCertificate(nonce); - X509Certificate cert2 = getSSLClientCertificate(request); - if (cert1 == null) { - CMS.debug("ProfileProcessServlet: Unknown nonce"); - } else if (cert1 != null && cert2 != null && cert1.equals(cert2)) { - nonceVerified = true; - mNonces.removeNonce(nonce); - } - } else { - CMS.debug("ProfileProcessServlet: Missing nonce"); - } - CMS.debug("ProfileProcessServlet: nonceVerified=" + nonceVerified); - if (!nonceVerified) { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_AUTHORIZATION_ERROR")); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } - return; - } - } - - CMS.debug("ProfileProcessServlet: start serving"); - - // (1) Read request from the database - - // (2) Get profile id from the request - if (mProfileSubId == null || mProfileSubId.equals("")) { - mProfileSubId = IProfileSubsystem.ID; - } - CMS.debug("ProfileProcessServlet: SubId=" + mProfileSubId); - IProfileSubsystem ps = (IProfileSubsystem) - CMS.getSubsystem(mProfileSubId); - - if (ps == null) { - CMS.debug("ProfileProcessServlet: ProfileSubsystem not found"); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } - return; - } - - // retrieve request - IAuthority authority = (IAuthority) CMS.getSubsystem(mAuthorityId); - - if (authority == null) { - CMS.debug("ProfileProcessServlet: Authority " + mAuthorityId + - " not found"); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } - return; - } - IRequestQueue queue = authority.getRequestQueue(); + RequestProcessor processor = new RequestProcessor("caProfileProcess", locale); - if (queue == null) { - CMS.debug("ProfileProcessServlet: Request Queue of " + - mAuthorityId + " not found"); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } + String op = request.getParameter("op"); + if (op == null) { + CMS.debug("ProfileProcessServlet: No op found"); + setError(args, CMS.getUserMessage(locale, "CMS_OP_NOT_FOUND"), request, response); return; } String requestId = request.getParameter("requestId"); - if (requestId == null || requestId.equals("")) { CMS.debug("ProfileProcessServlet: Request Id not found"); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_REQUEST_ID_NOT_FOUND")); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } + setError(args, CMS.getUserMessage(locale, "CMS_REQUEST_ID_NOT_FOUND"), request, response); return; } - IRequest req = null; - - CMS.debug("ProfileProcessServlet: requestId=" + requestId); - try { - req = queue.findRequest(new RequestId(requestId)); - } catch (EBaseException e) { - // request not found - CMS.debug("ProfileProcessServlet: request not found requestId=" + - requestId + " " + e.toString()); - } + IRequest req = processor.getRequest(requestId); if (req == null) { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_REQUEST_NOT_FOUND", requestId)); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } - return; - } - - // check if the request is in one of the terminal states - if (!req.getRequestStatus().equals(RequestStatus.PENDING)) { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_REQUEST_NOT_PENDING", requestId)); - args.set(ARG_REQUEST_ID, requestId); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } + setError(args, CMS.getUserMessage(locale, "CMS_REQUEST_NOT_FOUND", requestId), request, response); return; } String profileId = req.getExtDataInString("profileId"); - - CMS.debug("ProfileProcessServlet: profileId=" + profileId); if (profileId == null || profileId.equals("")) { CMS.debug("ProfileProcessServlet: Profile Id not found"); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_PROFILE_ID_NOT_FOUND")); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } - return; - } - - String op = request.getParameter("op"); - if (op == null) { - CMS.debug("ProfileProcessServlet: No op found"); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_OP_NOT_FOUND")); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } + setError(args, CMS.getUserMessage(locale, "CMS_PROFILE_ID_NOT_FOUND"), request, response); return; } + CMS.debug("ProfileProcessServlet: profileId=" + profileId); - IProfile profile = null; + // set request in cmsReq for later retrieval + cmsReq.setIRequest(req); + AgentEnrollmentRequestData data = null; try { - profile = ps.getProfile(profileId); - } catch (EProfileException e) { - // profile not found - CMS.debug("ProfileProcessServlet: profile not found " + - " " + " profileId=" + profileId + " " + e.toString()); - } - if (profile == null) { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_PROFILE_NOT_FOUND", profileId)); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } + data = processor.processRequest(cmsReq, req, op); + } catch (EAuthException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + setError(args, e.getMessage(), request, response); return; - } - - // if profile is currently disabled, dont do anything - if (!ps.isProfileEnable(profileId)) { - CMS.debug("ProfileProcessServlet: Profile Id not enabled"); - args.set(ARG_OP, op); - args.set(ARG_REQUEST_ID, req.getRequestId().toString()); - args.set(ARG_REQUEST_STATUS, req.getRequestStatus().toString()); - args.set(ARG_REQUEST_TYPE, req.getRequestType()); - args.set(ARG_PROFILE_ID, profileId); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_PROFILE_ID_NOT_ENABLED")); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } + } catch (EAuthzException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + setError(args, e.getMessage(), request, response); + return; + } catch (BadRequestDataException e) { + setError(args, e.getMessage(), request, response); return; - } - - args.set(ARG_ERROR_CODE, "0"); - args.set(ARG_ERROR_REASON, ""); - - try { - if (op.equals("assign")) { - String owner = req.getRequestOwner(); - - // assigned owner - if (owner != null && owner.length() > 0) { - if (!grantPermission(req, authToken)) { - CMS.debug("ProfileProcessServlet: Permission not granted to assign request."); - args.set(ARG_OP, op); - args.set(ARG_REQUEST_ID, req.getRequestId().toString()); - args.set(ARG_REQUEST_STATUS, req.getRequestStatus().toString()); - args.set(ARG_REQUEST_TYPE, req.getRequestType()); - args.set(ARG_PROFILE_ID, profileId); - args.set(ARG_PROFILE_ID, profileId); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, "CMS_PROFILE_DENY_OPERATION")); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } - return; - } - } - assignRequest(request, args, req, queue, profile, locale); - } else { - if (grantPermission(req, authToken)) { - if (op.equals("approve")) { - checkProfileVersion(profile, req, locale); - updateValues(request, req, queue, profile, locale); - updateNotes(request, req); - approveRequest(request, args, req, queue, profile, locale); - } else if (op.equals("reject")) { - updateNotes(request, req); - rejectRequest(request, args, req, queue, profile, locale); - } else if (op.equals("cancel")) { - updateNotes(request, req); - cancelRequest(request, args, req, queue, profile, locale); - } else if (op.equals("update")) { - checkProfileVersion(profile, req, locale); - updateValues(request, req, queue, profile, locale); - updateNotes(request, req); - } else if (op.equals("validate")) { - updateValues(request, req, queue, profile, locale); - } else if (op.equals("unassign")) { - unassignRequest(request, args, req, queue, profile, locale); - } - } else { - CMS.debug("ProfileProcessServlet: Permission not granted to approve/reject/cancel/update/validate/unassign request."); - args.set(ARG_OP, op); - args.set(ARG_REQUEST_ID, req.getRequestId().toString()); - args.set(ARG_REQUEST_STATUS, req.getRequestStatus().toString()); - args.set(ARG_REQUEST_TYPE, req.getRequestType()); - args.set(ARG_PROFILE_ID, profileId); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, "CMS_PROFILE_DENY_OPERATION")); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } - return; - } - } - - // commit request to the storage - if (!op.equals("validate")) { - try { - if (op.equals("approve")) { - queue.markAsServiced(req); - } else { - queue.updateRequest(req); - } - } catch (EBaseException e) { - CMS.debug("ProfileProcessServlet: Request commit error " + - e.toString()); - // save request to disk - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } - return; - } - } } catch (ERejectException e) { - CMS.debug("ProfileProcessServlet: execution rejected " + - e.toString()); + CMS.debug("ProfileProcessServlet: execution rejected " + e.toString()); args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_PROFILE_REJECTED", e.toString())); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, "CMS_PROFILE_REJECTED", e.toString())); } catch (EDeferException e) { - CMS.debug("ProfileProcessServlet: execution defered " + - e.toString()); + CMS.debug("ProfileProcessServlet: execution defered " + e.toString()); args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_PROFILE_DEFERRED", e.toString())); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, "CMS_PROFILE_DEFERRED", e.toString())); } catch (EPropertyException e) { - CMS.debug("ProfileProcessServlet: execution error " + - e.toString()); + CMS.debug("ProfileProcessServlet: execution error " + e.toString()); args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_PROFILE_PROPERTY_ERROR", e.toString())); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, "CMS_PROFILE_PROPERTY_ERROR", e.toString())); } catch (EProfileException e) { - CMS.debug("ProfileProcessServlet: execution error " + - e.toString()); + CMS.debug("ProfileProcessServlet: execution error " + e.toString()); args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } catch (EBaseException e) { + setError(args, e.getMessage(), request, response); + return; } args.set(ARG_OP, op); @@ -471,490 +143,33 @@ public class ProfileProcessServlet extends ProfileServlet { args.set(ARG_REQUEST_STATUS, req.getRequestStatus().toString()); args.set(ARG_REQUEST_TYPE, req.getRequestType()); args.set(ARG_PROFILE_ID, profileId); - outputTemplate(request, response, args); - if (statsSub != null) { - statsSub.endTiming("approval"); - } - } - public boolean grantPermission(IRequest req, IAuthToken token) { - - try { - boolean enable = CMS.getConfigStore().getBoolean("request.assignee.enable", - false); - if (!enable) - return true; - String owner = req.getRequestOwner(); - - // unassigned owner - if (owner == null || owner.length() == 0) - return true; - String uid = token.getInString(IAuthToken.USER_ID); - if (uid.equals(owner)) - return true; - } catch (Exception e) { - } - - return false; - } - - /** - * Check if the request creation time is older than the profile - * lastModified attribute. - */ - protected void checkProfileVersion(IProfile profile, IRequest req, - Locale locale) throws EProfileException { - IConfigStore profileConfig = profile.getConfigStore(); - if (profileConfig != null) { - String lastModified = null; - try { - lastModified = profileConfig.getString("lastModified", ""); - } catch (EBaseException e) { - CMS.debug(e.toString()); - throw new EProfileException(e.toString()); - } - if (!lastModified.equals("")) { - Date profileModifiedAt = new Date(Long.parseLong(lastModified)); - CMS.debug("ProfileProcessServlet: Profile Last Modified=" + - profileModifiedAt); - Date reqCreatedAt = req.getCreationTime(); - CMS.debug("ProfileProcessServlet: Request Created At=" + - reqCreatedAt); - if (profileModifiedAt.after(reqCreatedAt)) { - CMS.debug("Profile Newer Than Request"); - throw new ERejectException("Profile Newer Than Request"); - } - } - } - } - - protected void assignRequest(ServletRequest request, ArgSet args, - IRequest req, - IRequestQueue queue, IProfile profile, Locale locale) - throws EProfileException { - - String id = auditSubjectID(); - req.setRequestOwner(id); - } - - protected void unassignRequest(ServletRequest request, ArgSet args, - IRequest req, - IRequestQueue queue, IProfile profile, Locale locale) - throws EProfileException { - - req.setRequestOwner(""); - } - - /** - * Cancel request - * <P> - * - * (Certificate Request Processed - a manual "agent" profile based cert cancellation) - * <P> - * - * <ul> - * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been - * through the approval process - * </ul> - * - * @param request the servlet request - * @param args argument set - * @param req the certificate request - * @param queue the certificate request queue - * @param profile this profile - * @param locale the system locale - * @exception EProfileException an error related to this profile has - * occurred - */ - protected void cancelRequest(ServletRequest request, ArgSet args, - IRequest req, - IRequestQueue queue, IProfile profile, Locale locale) - throws EProfileException { - String auditMessage = null; - String auditSubjectID = auditSubjectID(); - String auditRequesterID = auditRequesterID(req); - String auditInfoValue = auditInfoValue(req); - - // try { - req.setRequestStatus(RequestStatus.CANCELED); - - // store a message in the signed audit log file - auditMessage = CMS.getLogMessage( - LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, - auditSubjectID, - ILogger.SUCCESS, - auditRequesterID, - ILogger.SIGNED_AUDIT_CANCELLATION, - auditInfoValue); - - audit(auditMessage); - // } catch( EProfileException eAudit1 ) { - // // store a message in the signed audit log file - // auditMessage = CMS.getLogMessage( - // LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, - // auditSubjectID, - // ILogger.FAILURE, - // auditRequesterID, - // ILogger.SIGNED_AUDIT_CANCELLATION, - // auditInfoValue ); - // - // audit( auditMessage ); - // } - } - - /** - * Reject request - * <P> - * - * (Certificate Request Processed - a manual "agent" profile based cert rejection) - * <P> - * - * <ul> - * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been - * through the approval process - * </ul> - * - * @param request the servlet request - * @param args argument set - * @param req the certificate request - * @param queue the certificate request queue - * @param profile this profile - * @param locale the system locale - * @exception EProfileException an error related to this profile has - * occurred - */ - protected void rejectRequest(ServletRequest request, ArgSet args, - IRequest req, - IRequestQueue queue, IProfile profile, Locale locale) - throws EProfileException { - String auditMessage = null; - String auditSubjectID = auditSubjectID(); - String auditRequesterID = auditRequesterID(req); - String auditInfoValue = auditInfoValue(req); - - // try { - req.setRequestStatus(RequestStatus.REJECTED); - - // store a message in the signed audit log file - auditMessage = CMS.getLogMessage( - LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, - auditSubjectID, - ILogger.SUCCESS, - auditRequesterID, - ILogger.SIGNED_AUDIT_REJECTION, - auditInfoValue); - - audit(auditMessage); - // } catch( EProfileException eAudit1 ) { - // // store a message in the signed audit log file - // auditMessage = CMS.getLogMessage( - // LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, - // auditSubjectID, - // ILogger.FAILURE, - // auditRequesterID, - // ILogger.SIGNED_AUDIT_REJECTION, - // auditInfoValue ); - // - // audit( auditMessage ); - // } - } - - /** - * Approve request - * <P> - * - * (Certificate Request Processed - a manual "agent" profile based cert acceptance) - * <P> - * - * <ul> - * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been - * through the approval process - * </ul> - * - * @param request the servlet request - * @param args argument set - * @param req the certificate request - * @param queue the certificate request queue - * @param profile this profile - * @param locale the system locale - * @exception EProfileException an error related to this profile has - * occurred - */ - protected void approveRequest(ServletRequest request, ArgSet args, - IRequest req, - IRequestQueue queue, IProfile profile, Locale locale) - throws EProfileException { - String auditMessage = null; - String auditSubjectID = auditSubjectID(); - String auditRequesterID = auditRequesterID(req); - - try { - profile.execute(req); - req.setRequestStatus(RequestStatus.COMPLETE); + String errorCode = ((ArgString) args.get(ARG_ERROR_CODE)).getValue(); + if (op.equals("approve") && errorCode.equals("0") && (data != null)) { ArgList outputlist = new ArgList(); - Enumeration<String> outputIds = profile.getProfileOutputIds(); - - if (outputIds != null) { - while (outputIds.hasMoreElements()) { - String outputId = outputIds.nextElement(); - IProfileOutput profileOutput = profile.getProfileOutput( - outputId); - - Enumeration<String> outputNames = profileOutput.getValueNames(); - - if (outputNames != null) { - while (outputNames.hasMoreElements()) { - ArgSet outputset = new ArgSet(); - String outputName = - outputNames.nextElement(); - IDescriptor outputDesc = - profileOutput.getValueDescriptor(locale, - outputName); - - if (outputDesc == null) - continue; - String outputSyntax = outputDesc.getSyntax(); - String outputConstraint = - outputDesc.getConstraint(); - String outputValueName = - outputDesc.getDescription(locale); - String outputValue = null; - - try { - outputValue = profileOutput.getValue( - outputName, - locale, req); - } catch (EProfileException e) { - CMS.debug("ProfileSubmitServlet: " + - e.toString()); - } - - outputset.set(ARG_OUTPUT_ID, outputName); - outputset.set(ARG_OUTPUT_SYNTAX, outputSyntax); - outputset.set(ARG_OUTPUT_CONSTRAINT, - outputConstraint); - outputset.set(ARG_OUTPUT_NAME, outputValueName); - outputset.set(ARG_OUTPUT_VAL, outputValue); - outputlist.add(outputset); - } - } + for (ProfileOutput output: data.getOutputs()) { + for (ProfileAttribute attr: output.getAttrs()){ + ArgSet outputset = new ArgSet(); + Descriptor desc = attr.getDescriptor(); + outputset.set(ARG_OUTPUT_ID, attr.getName()); + outputset.set(ARG_OUTPUT_SYNTAX, desc.getSyntax()); + outputset.set(ARG_OUTPUT_CONSTRAINT, desc.getConstraint()); + outputset.set(ARG_OUTPUT_NAME, desc.getDescription(locale)); + outputset.set(ARG_OUTPUT_VAL, attr.getValue()); + outputlist.add(outputset); } } args.set(ARG_OUTPUT_LIST, outputlist); - - // retrieve the certificate - X509CertImpl theCert = req.getExtDataInCert( - IEnrollProfile.REQUEST_ISSUED_CERT); - - // store a message in the signed audit log file - auditMessage = CMS.getLogMessage( - LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, - auditSubjectID, - ILogger.SUCCESS, - auditRequesterID, - ILogger.SIGNED_AUDIT_ACCEPTANCE, - auditInfoCertValue(theCert)); - - audit(auditMessage); - - } catch (EProfileException eAudit1) { - // store a message in the signed audit log file - auditMessage = CMS.getLogMessage( - LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, - auditSubjectID, - ILogger.FAILURE, - auditRequesterID, - ILogger.SIGNED_AUDIT_ACCEPTANCE, - ILogger.SIGNED_AUDIT_EMPTY_VALUE); - - audit(auditMessage); - - CMS.debug("ProfileProcessServlet: about to throw EProfileException because of bad profile execute."); - throw new EProfileException(eAudit1.toString()); - - } - } - - protected void updateValues(ServletRequest request, IRequest req, - IRequestQueue queue, IProfile profile, Locale locale) - throws ERejectException, EDeferException, EPropertyException { - String profileSetId = req.getExtDataInString("profileSetId"); - - Enumeration<ProfilePolicy> policies = profile.getProfilePolicies(profileSetId); - int count = 0; - - while (policies.hasMoreElements()) { - ProfilePolicy policy = policies.nextElement(); - - setValue(locale, count, policy, req, request); - count++; - } - - policies = profile.getProfilePolicies(profileSetId); - count = 0; - while (policies.hasMoreElements()) { - ProfilePolicy policy = policies.nextElement(); - - validate(locale, count, policy, req, request); - count++; } + outputTemplate(request, response, args); } - protected void updateNotes(ServletRequest request, IRequest req) { - String notes = request.getParameter(ARG_REQUEST_NOTES); - - if (notes != null) { - req.setExtData("requestNotes", notes); - } - } - - protected void validate(Locale locale, int count, - IProfilePolicy policy, IRequest req, ServletRequest request) - throws ERejectException, EDeferException { - IPolicyConstraint con = policy.getConstraint(); - - con.validate(req); - } - - protected void setValue(Locale locale, int count, - IProfilePolicy policy, IRequest req, ServletRequest request) - throws EPropertyException { - // handle default policy - IPolicyDefault def = policy.getDefault(); - Enumeration<String> defNames = def.getValueNames(); - - while (defNames.hasMoreElements()) { - String defName = defNames.nextElement(); - String defValue = request.getParameter(defName); - - def.setValue(defName, locale, req, defValue); - } - } - - /** - * Signed Audit Log Requester ID - * - * This method is called to obtain the "RequesterID" for - * a signed audit log message. - * <P> - * - * @param request the actual request - * @return id string containing the signed audit log message RequesterID - */ - private String auditRequesterID(IRequest request) { - // if no signed audit object exists, bail - if (mSignedAuditLogger == null) { - return null; - } - - String requesterID = ILogger.UNIDENTIFIED; - - if (request != null) { - // overwrite "requesterID" if and only if "id" != null - String id = request.getRequestId().toString(); - - if (id != null) { - requesterID = id.trim(); - } - } - - return requesterID; - } - - /** - * Signed Audit Log Info Value - * - * This method is called to obtain the "reason" for - * a signed audit log message. - * <P> - * - * @param request the actual request - * @return reason string containing the signed audit log message reason - */ - private String auditInfoValue(IRequest request) { - // if no signed audit object exists, bail - if (mSignedAuditLogger == null) { - return null; - } - - String reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE; - - if (request != null) { - // overwrite "reason" if and only if "info" != null - String info = - request.getExtDataInString(SIGNED_AUDIT_CERT_REQUEST_REASON); - - if (info != null) { - reason = info.trim(); - - // overwrite "reason" if and only if "reason" is empty - if (reason.equals("")) { - reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE; - } - } - } - - return reason; - } - - /** - * Signed Audit Log Info Certificate Value - * - * This method is called to obtain the certificate from the passed in - * "X509CertImpl" for a signed audit log message. - * <P> - * - * @param x509cert an X509CertImpl - * @return cert string containing the certificate - */ - 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 (!Character.isWhitespace(base64Data.charAt(i))) { - sb.append(base64Data.charAt(i)); - } - } - cert = sb.toString(); - } - - if (cert != null) { - cert = cert.trim(); - - if (cert.equals("")) { - return ILogger.SIGNED_AUDIT_EMPTY_VALUE; - } else { - return cert; - } - } else { - return ILogger.SIGNED_AUDIT_EMPTY_VALUE; - } + private void setError(ArgSet args, String reason, HttpServletRequest request, HttpServletResponse response) + throws EBaseException { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, reason); + outputTemplate(request, response, args); } } diff --git a/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java index e975161da..be331d6ef 100644 --- a/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java +++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; import java.util.Enumeration; +import java.util.LinkedHashSet; import java.util.Locale; import javax.servlet.ServletConfig; @@ -158,6 +159,9 @@ public class ProfileServlet extends CMSServlet { protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger(); + // stats + protected LinkedHashSet<String> statEvents = new LinkedHashSet<String>(); + public ProfileServlet() { super(); } @@ -291,6 +295,55 @@ public class ProfileServlet extends CMSServlet { } } + public void outputTemplate(boolean isXML, HttpServletResponse response, ArgSet args) + throws EBaseException { + if (isXML) { + response.setContentType("text/xml"); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + outputThisAsXML(bos, args); + try { + response.setContentLength(bos.size()); + bos.writeTo(response.getOutputStream()); + } catch (Exception e) { + CMS.debug("outputTemplate error " + e); + } + return; + } + startTiming("output_template"); + + BufferedReader reader = null; + try { + reader = new BufferedReader(new FileReader(mTemplate)); + + response.setContentType("text/html; charset=UTF-8"); + + PrintWriter writer = response.getWriter(); + + // output template + String line = null; + + do { + line = reader.readLine(); + if (line != null) { + if (line.indexOf("<CMS_TEMPLATE>") == -1) { + writer.println(line); + } else { + // output javascript parameters + writer.println("<script type=\"text/javascript\">"); + outputData(writer, args); + writer.println("</script>"); + } + } + } while (line != null); + reader.close(); + } catch (IOException e) { + CMS.debug(e); + throw new EBaseException(e.toString()); + } finally { + endTiming("output_template"); + } + } + protected void outputArgList(PrintWriter writer, String name, ArgList list) throws IOException { @@ -321,6 +374,22 @@ public class ProfileServlet extends CMSServlet { } } + public void startTiming(String event) { + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.startTiming(event, true); + } + statEvents.add(event); + } + + public void endTiming(String event) { + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.endTiming(event); + } + statEvents.remove(event); + } + protected String escapeJavaScriptString(String v) { int l = v.length(); char in[] = new char[l]; diff --git a/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java index 85ef4fa0f..7b0813d71 100644 --- a/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java +++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java @@ -17,58 +17,38 @@ // --- END COPYRIGHT BLOCK --- package com.netscape.cms.servlet.profile; -import java.math.BigInteger; -import java.security.cert.CertificateEncodingException; -import java.security.cert.X509Certificate; -import java.util.Date; import java.util.Enumeration; +import java.util.HashMap; import java.util.Locale; -import java.util.StringTokenizer; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import netscape.security.x509.BasicConstraintsExtension; import netscape.security.x509.X509CertImpl; import netscape.security.x509.X509CertInfo; import org.w3c.dom.Node; import com.netscape.certsrv.apps.CMS; -import com.netscape.certsrv.authentication.IAuthToken; -import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.authentication.EAuthException; +import com.netscape.certsrv.authorization.EAuthzException; +import com.netscape.certsrv.base.BadRequestDataException; import com.netscape.certsrv.base.EBaseException; -import com.netscape.certsrv.base.MetaInfo; -import com.netscape.certsrv.base.SessionContext; -import com.netscape.certsrv.ca.ICertificateAuthority; -import com.netscape.certsrv.dbs.certdb.ICertRecord; -import com.netscape.certsrv.dbs.certdb.ICertificateRepository; -import com.netscape.certsrv.logging.ILogger; -import com.netscape.certsrv.profile.EDeferException; import com.netscape.certsrv.profile.EProfileException; -import com.netscape.certsrv.profile.ERejectException; import com.netscape.certsrv.profile.IEnrollProfile; import com.netscape.certsrv.profile.IProfile; -import com.netscape.certsrv.profile.IProfileAuthenticator; -import com.netscape.certsrv.profile.IProfileContext; -import com.netscape.certsrv.profile.IProfileInput; import com.netscape.certsrv.profile.IProfileOutput; -import com.netscape.certsrv.profile.IProfileSubsystem; import com.netscape.certsrv.property.IDescriptor; -import com.netscape.certsrv.request.INotify; 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.template.ArgList; import com.netscape.certsrv.template.ArgSet; -import com.netscape.certsrv.util.IStatsSubsystem; -import com.netscape.cms.servlet.common.AuthCredentials; +import com.netscape.cms.servlet.cert.EnrollmentProcessor; +import com.netscape.cms.servlet.cert.RenewalProcessor; import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.processors.Processor; import com.netscape.cmsutil.util.Cert; -import com.netscape.cmsutil.util.Utils; import com.netscape.cmsutil.xml.XMLObject; /** @@ -83,31 +63,9 @@ public class ProfileSubmitServlet extends ProfileServlet { * */ private static final long serialVersionUID = 7557922703180866442L; - private static final String ARG_AUTH_TOKEN = "auth_token"; - private static final String ARG_REQUEST_OWNER = "requestOwner"; - private static final String PROP_PROFILE_ID = "profileId"; - private static final String PROP_AUTHORITY_ID = "authorityId"; private final static String SUCCESS = "0"; private final static String FAILED = "1"; - private String mProfileId = null; - private String mProfileSubId = null; - private String mAuthorityId = null; - - private final static String[] SIGNED_AUDIT_AUTOMATED_REJECTION_REASON = new String[] { - - /* 0 */"automated profile cert request rejection: " - + "indeterminate reason for inability to process " - + "cert request due to an EBaseException" - }; - private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED = - "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5"; - - private final static String LOGGING_SIGNED_AUDIT_AUTH_FAIL = - "LOGGING_SIGNED_AUDIT_AUTH_FAIL_4"; - private final static String LOGGING_SIGNED_AUDIT_AUTH_SUCCESS = - "LOGGING_SIGNED_AUDIT_AUTH_SUCCESS_3"; - public ProfileSubmitServlet() { } @@ -123,273 +81,122 @@ public class ProfileSubmitServlet extends ProfileServlet { */ public void init(ServletConfig sc) throws ServletException { super.init(sc); - mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID); - mProfileId = sc.getInitParameter(PROP_PROFILE_ID); - } - - private void setInputsIntoContext(HttpServletRequest request, IProfile profile, IProfileContext ctx) { - // passing inputs into context - Enumeration<String> inputIds = profile.getProfileInputIds(); - - if (inputIds != null) { - while (inputIds.hasMoreElements()) { - String inputId = inputIds.nextElement(); - IProfileInput profileInput = profile.getProfileInput(inputId); - Enumeration<String> inputNames = profileInput.getValueNames(); - - while (inputNames.hasMoreElements()) { - String inputName = inputNames.nextElement(); - if (request.getParameter(inputName) != null) { - // all subject name parameters start with sn_, no other input parameters do - if (inputName.matches("^sn_.*")) { - ctx.set(inputName, escapeValueRfc1779(request.getParameter(inputName), false).toString()); - } else { - ctx.set(inputName, request.getParameter(inputName)); - } - } - } - } - } - } - /* - * fill input info from "request" to context. - * This is expected to be used by renewal where the request - * is retrieved from request record + /** + * Process the HTTP request + * <P> + * + * (Certificate Request Processed - either an automated "EE" profile based cert acceptance, or an automated "EE" + * profile based cert rejection) + * <P> + * + * <ul> + * <li>http.param profileId ID of profile to use to process request + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + * </ul> + * + * @param cmsReq the object holding the request and response information + * @exception EBaseException an error has occurred */ - private void setInputsIntoContext(IRequest request, IProfile profile, IProfileContext ctx, Locale locale) { - // passing inputs into context - Enumeration<String> inputIds = profile.getProfileInputIds(); - - if (inputIds != null) { - while (inputIds.hasMoreElements()) { - String inputId = inputIds.nextElement(); - IProfileInput profileInput = profile.getProfileInput(inputId); - Enumeration<String> inputNames = profileInput.getValueNames(); - - while (inputNames.hasMoreElements()) { - String inputName = inputNames.nextElement(); - String inputValue = ""; - CMS.debug("ProfileSubmitServlet: setInputsIntoContext() getting input name= " + inputName); - try { - inputValue = profileInput.getValue(inputName, locale, request); - } catch (Exception e) { - CMS.debug("ProfileSubmitServlet: setInputsIntoContext() getvalue() failed: " + e.toString()); - } - - if (inputValue != null) { - CMS.debug("ProfileSubmitServlet: setInputsIntoContext() setting value in ctx:" + inputValue); - ctx.set(inputName, inputValue); - } else { - CMS.debug("ProfileSubmitServlet: setInputsIntoContext() value null"); - } - } - } - } - } - - private void setCredentialsIntoContext(HttpServletRequest request, IProfileAuthenticator authenticator, - IProfileContext ctx) { - Enumeration<String> authIds = authenticator.getValueNames(); - - if (authIds != null) { - CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authNames not null"); - while (authIds.hasMoreElements()) { - String authName = authIds.nextElement(); + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest request = cmsReq.getHttpReq(); + HttpServletResponse response = cmsReq.getHttpResp(); + boolean xmlOutput = getXMLOutput(request); - CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authName:" + - authName); - if (request.getParameter(authName) != null) { - CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authName found in request"); - ctx.set(authName, request.getParameter(authName)); - } else { - CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authName not found in request"); - } - } - } else { - CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authIds` null"); - } - } + Locale locale = getLocale(request); - String getUidFromDN(String userdn) { - StringTokenizer st = new StringTokenizer(userdn, ","); - while (st.hasMoreTokens()) { - String t = st.nextToken(); - int i = t.indexOf("="); + HashMap<String, Object> results = null; + String renewal = request.getParameter("renewal"); - if (i == -1) { - continue; - } - String n = t.substring(0, i); - if (n.equalsIgnoreCase("uid")) { - String v = t.substring(i + 1); - CMS.debug("ProfileSubmitServlet:: getUidFromDN(): uid found:" + v); - return v; + try { + if ((renewal != null) && (renewal.equalsIgnoreCase("true"))) { + CMS.debug("ProfileSubmitServlet: isRenewal true"); + RenewalProcessor processor = new RenewalProcessor("caProfileSubmit", locale); + results = processor.processRenewal(cmsReq); } else { - continue; + CMS.debug("ProfileSubmitServlet: isRenewal false"); + EnrollmentProcessor processor = new EnrollmentProcessor("caProfileSubmit", locale); + results = processor.processEnrollment(cmsReq); } + } catch (BadRequestDataException e) { + CMS.debug("ProfileSubmitServlet: bad data provided in processing request: " + e.toString()); + errorExit(response, xmlOutput, e.getMessage(), null); + return; + } catch (EAuthzException e) { + CMS.debug("ProfileSubmitServlet: authorization error in processing request: " + e.toString()); + errorExit(response, xmlOutput, e.getMessage(), null); + return; + } catch (EAuthException e) { + CMS.debug("ProfileSubmitServlet: authentication error in processing request: " + e.toString()); + errorExit(response, xmlOutput, e.getMessage(), null); + return; + } catch (EBaseException e) { + e.printStackTrace(); + CMS.debug("ProfileSubmitServlet: error in processing request: " + e.toString()); + errorExit(response, xmlOutput, e.getMessage(), null); + return; } - return null; - } - /* - * authenticate for renewal - more to add necessary params/values - * to the session context - */ - public IAuthToken authenticate(IProfileAuthenticator authenticator, - HttpServletRequest request, IRequest origReq, SessionContext context) - throws EBaseException { - IAuthToken authToken = authenticate(authenticator, request); - // For renewal, fill in necessary params - if (authToken != null) { - String ouid = origReq.getExtDataInString("auth_token.uid"); - // if the orig cert was manually approved, then there was - // no auth token uid. Try to get the uid from the cert dn - // itself, if possible - if (ouid == null) { - String sdn = (String) context.get("origSubjectDN"); - if (sdn != null) { - ouid = getUidFromDN(sdn); - if (ouid != null) - CMS.debug("ProfileSubmitServlet: renewal: authToken original uid not found"); - } - } else { - CMS.debug("ProfileSubmitServlet: renewal: authToken original uid found in orig request auth_token"); - } - String auid = authToken.getInString("uid"); - if (auid != null) { // not through ssl client auth - CMS.debug("ProfileSubmitServlet: renewal: authToken uid found:" + auid); - // authenticated with uid - // put "orig_req.auth_token.uid" so that authz with - // UserOrigReqAccessEvaluator will work - if (ouid != null) { - context.put("orig_req.auth_token.uid", ouid); - CMS.debug("ProfileSubmitServlet: renewal: authToken original uid found:" + ouid); - } else { - CMS.debug("ProfileSubmitServlet: renewal: authToken original uid not found"); - } - } else { // through ssl client auth? - CMS.debug("ProfileSubmitServlet: renewal: authToken uid not found:"); - // put in orig_req's uid - if (ouid != null) { - CMS.debug("ProfileSubmitServlet: renewal: origReq uid not null:" + ouid + ". Setting authtoken"); - authToken.set("uid", ouid); - context.put(SessionContext.USER_ID, ouid); - } else { - CMS.debug("ProfileSubmitServlet: renewal: origReq uid not found"); - // throw new EBaseException("origReq uid not found"); + IRequest[] reqs = (IRequest []) results.get(Processor.ARG_REQUESTS); + String errorCode = (String) results.get(Processor.ARG_ERROR_CODE); + String errorReason = (String) results.get(Processor.ARG_ERROR_REASON); + IProfile profile = (IProfile) results.get(Processor.ARG_PROFILE); + ArgSet args = new ArgSet(); + + if (errorCode != null) { + if (xmlOutput) { + String requestIds = ""; + for (IRequest req : reqs) { + requestIds += " " + req.getRequestId().toString(); } - } - String userdn = origReq.getExtDataInString("auth_token.userdn"); - if (userdn != null) { - CMS.debug("ProfileSubmitServlet: renewal: origReq userdn not null:" + userdn + ". Setting authtoken"); - authToken.set("userdn", userdn); + outputError(response, errorCode, errorReason, requestIds); } else { - CMS.debug("ProfileSubmitServlet: renewal: origReq userdn not found"); - // throw new EBaseException("origReq userdn not found"); - } - } else { - CMS.debug("ProfileSubmitServlet: renewal: authToken null"); - } - return authToken; - } - - public IAuthToken authenticate(IProfileAuthenticator authenticator, - HttpServletRequest request) throws EBaseException { - AuthCredentials credentials = new AuthCredentials(); - - // build credential - Enumeration<String> authNames = authenticator.getValueNames(); - - if (authNames != null) { - while (authNames.hasMoreElements()) { - String authName = authNames.nextElement(); + ArgList requestlist = new ArgList(); - credentials.set(authName, request.getParameter(authName)); + for (IRequest req : reqs) { + ArgSet requestset = new ArgSet(); + requestset.set(ARG_REQUEST_ID, req.getRequestId().toString()); + requestlist.add(requestset); + } + args.set(ARG_REQUEST_LIST, requestlist); + args.set(ARG_ERROR_CODE, errorCode); + args.set(ARG_ERROR_REASON, errorReason); + outputTemplate(request, response, args); } + return; } - credentials.set("clientHost", request.getRemoteHost()); - IAuthToken authToken = authenticator.authenticate(credentials); + if (xmlOutput) { + xmlOutput(response, profile, locale, reqs); + } else { + ArgList outputlist = new ArgList(); + for (int k = 0; k < reqs.length; k++) { - SessionContext sc = SessionContext.getContext(); - if (sc != null) { - sc.put(SessionContext.AUTH_MANAGER_ID, authenticator.getName()); - String userid = authToken.getInString(IAuthToken.USER_ID); - if (userid != null) { - sc.put(SessionContext.USER_ID, userid); + setOutputIntoArgs(profile, outputlist, locale, reqs[k]); + args.set(ARG_OUTPUT_LIST, outputlist); } - } - - return authToken; - } - private void setInputsIntoRequest(HttpServletRequest request, IProfile profile, IRequest req) { - Enumeration<String> inputIds = profile.getProfileInputIds(); + CMS.debug("ProfileSubmitServlet: done serving"); - if (inputIds != null) { - while (inputIds.hasMoreElements()) { - String inputId = inputIds.nextElement(); - IProfileInput profileInput = profile.getProfileInput(inputId); - Enumeration<String> inputNames = profileInput.getValueNames(); + ArgList requestlist = new ArgList(); - if (inputNames != null) { - while (inputNames.hasMoreElements()) { - String inputName = inputNames.nextElement(); + for (int k = 0; k < reqs.length; k++) { + ArgSet requestset = new ArgSet(); - if (request.getParameter(inputName) != null) { - // special characters in subject names parameters must be escaped - if (inputName.matches("^sn_.*")) { - req.setExtData(inputName, escapeValueRfc1779(request.getParameter(inputName), false) - .toString()); - } else { - req.setExtData(inputName, request.getParameter(inputName)); - } - } - } - } + requestset.set(ARG_REQUEST_ID, + reqs[k].getRequestId().toString()); + requestlist.add(requestset); } - } - } - - /* - * fill input info from orig request to the renew request. - * This is expected to be used by renewal where the request - * is retrieved from request record - */ - private void setInputsIntoRequest(IRequest request, IProfile profile, IRequest req, Locale locale) { - // passing inputs into request - Enumeration<String> inputIds = profile.getProfileInputIds(); - - if (inputIds != null) { - while (inputIds.hasMoreElements()) { - String inputId = inputIds.nextElement(); - IProfileInput profileInput = profile.getProfileInput(inputId); - Enumeration<String> inputNames = profileInput.getValueNames(); + args.set(ARG_REQUEST_LIST, requestlist); + args.set(ARG_ERROR_CODE, "0"); + args.set(ARG_ERROR_REASON, ""); - while (inputNames.hasMoreElements()) { - String inputName = inputNames.nextElement(); - String inputValue = ""; - CMS.debug("ProfileSubmitServlet: setInputsIntoRequest() getting input name= " + inputName); - try { - inputValue = profileInput.getValue(inputName, locale, request); - } catch (Exception e) { - CMS.debug("ProfileSubmitServlet: setInputsIntoRequest() getvalue() failed: " + e.toString()); - } - - if (inputValue != null) { - CMS.debug("ProfileSubmitServlet: setInputsIntoRequest() setting value in ctx:" + inputValue); - req.setExtData(inputName, inputValue); - } else { - CMS.debug("ProfileSubmitServlet: setInputsIntoRequest() value null"); - } - } - } + outputTemplate(request, response, args); } - } private void setOutputIntoArgs(IProfile profile, ArgList outputlist, Locale locale, IRequest req) { @@ -418,7 +225,7 @@ public class ProfileSubmitServlet extends ProfileServlet { try { outputValue = profileOutput.getValue(outputName, - locale, req); + locale, req); } catch (EProfileException e) { CMS.debug("ProfileSubmitServlet: " + e.toString()); } @@ -435,26 +242,23 @@ public class ProfileSubmitServlet extends ProfileServlet { } } - /** - * Process the HTTP request - * <P> - * - * (Certificate Request Processed - either an automated "EE" profile based cert acceptance, or an automated "EE" - * profile based cert rejection) - * <P> - * - * <ul> - * <li>http.param profileId ID of profile to use to process request - * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been - * through the approval process - * </ul> - * - * @param cmsReq the object holding the request and response information - * @exception EBaseException an error has occurred - */ - public void process(CMSRequest cmsReq) throws EBaseException { - HttpServletRequest request = cmsReq.getHttpReq(); - HttpServletResponse response = cmsReq.getHttpResp(); + private void errorExit(HttpServletResponse response, boolean xmlOutput, String message, String requestId) + throws EBaseException { + if (xmlOutput) { + outputError(response, FAILED, message, requestId); + } else { + ArgSet args = new ArgSet(); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, message); + outputTemplate(xmlOutput, response, args); + } + + for (String event : statEvents) { + endTiming(event); + } + } + + private boolean getXMLOutput(HttpServletRequest request) { boolean xmlOutput = false; String v = request.getParameter("xml"); @@ -470,1002 +274,7 @@ public class ProfileSubmitServlet extends ProfileServlet { } else { CMS.debug("xmlOutput false"); } - - IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); - if (statsSub != null) { - statsSub.startTiming("enrollment", true /* main action */); - } - - Locale locale = getLocale(request); - ArgSet args = new ArgSet(); - - if (CMS.debugOn()) { - CMS.debug("Start of ProfileSubmitServlet Input Parameters"); - @SuppressWarnings("unchecked") - Enumeration<String> paramNames = request.getParameterNames(); - - while (paramNames.hasMoreElements()) { - String paramName = paramNames.nextElement(); - // added this facility so that password can be hidden, - // all sensitive parameters should be prefixed with - // __ (double underscores); however, in the event that - // a security parameter slips through, we perform multiple - // additional checks to insure that it is NOT displayed - if (paramName.startsWith("__") || - paramName.endsWith("password") || - paramName.endsWith("passwd") || - paramName.endsWith("pwd") || - paramName.equalsIgnoreCase("admin_password_again") || - paramName.equalsIgnoreCase("directoryManagerPwd") || - paramName.equalsIgnoreCase("bindpassword") || - paramName.equalsIgnoreCase("bindpwd") || - paramName.equalsIgnoreCase("passwd") || - paramName.equalsIgnoreCase("password") || - paramName.equalsIgnoreCase("pin") || - paramName.equalsIgnoreCase("pwd") || - paramName.equalsIgnoreCase("pwdagain") || - paramName.equalsIgnoreCase("uPasswd")) { - CMS.debug("ProfileSubmitServlet Input Parameter " + - paramName + "='(sensitive)'"); - } else { - CMS.debug("ProfileSubmitServlet Input Parameter " + - paramName + "='" + - request.getParameter(paramName) + "'"); - } - } - CMS.debug("End of ProfileSubmitServlet Input Parameters"); - } - - CMS.debug("ProfileSubmitServlet: start serving"); - - if (mProfileSubId == null || mProfileSubId.equals("")) { - mProfileSubId = IProfileSubsystem.ID; - } - CMS.debug("ProfileSubmitServlet: SubId=" + mProfileSubId); - IProfileSubsystem ps = (IProfileSubsystem) - CMS.getSubsystem(mProfileSubId); - - if (ps == null) { - CMS.debug("ProfileSubmitServlet: ProfileSubsystem not found"); - if (xmlOutput) { - outputError(response, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - } else { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - } - if (statsSub != null) { - statsSub.endTiming("enrollment"); - } - return; - } - - /* - * Renewal - Renewal is retrofitted into the Profile Enrollment - * Framework. The authentication and authorization are taken from - * the renewal profile, while the input (with requests) and grace - * period constraint are taken from the original cert's request record. - * - * Things to note: - * * the renew request will contain the original profile instead - * of the new - * * there is no request for system and admin certs generated at - * time of installation configuration. - */ - String renewal = request.getParameter("renewal"); - boolean isRenewal = false; - if ((renewal != null) && (renewal.equalsIgnoreCase("true"))) { - CMS.debug("ProfileSubmitServlet: isRenewal true"); - isRenewal = true; - request.setAttribute("reqType", "renewal"); - } else { - CMS.debug("ProfileSubmitServlet: isRenewal false"); - } - - String renewProfileId = null; - IRequest origReq = null; - Integer origSeqNum = 0; - - // if we did not configure profileId in xml file, - // then accept the user-provided one - String profileId = null; - - if (mProfileId == null) { - profileId = request.getParameter("profileId"); - } else { - profileId = mProfileId; - } - - CMS.debug("ProfileSubmitServlet: profileId " + profileId); - // This is the expiration date of the orig. cert that will - // be used in the RenewGracePeriodConstraint - Date origNotAfter = null; - String origSubjectDN = null; - - if (isRenewal) { - // dig up the original request to "clone" - renewProfileId = profileId; - CMS.debug("ProfileSubmitServlet: renewProfileId =" + renewProfileId); - IAuthority authority = (IAuthority) CMS.getSubsystem(mAuthorityId); - if (authority == null) { - CMS.debug("ProfileSubmitServlet: renewal: Authority " + mAuthorityId + - " not found"); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - return; - } - IRequestQueue queue = authority.getRequestQueue(); - - if (queue == null) { - CMS.debug("ProfileSubmitServlet: renewal: Request Queue of " + - mAuthorityId + " not found"); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - return; - } - - String serial = request.getParameter("serial_num"); - BigInteger certSerial = null; - // if serial number is sent with request, then the authentication - // method is not ssl client auth. In this case, an alternative - // authentication method is used (default: ldap based) - if (serial != null) { - CMS.debug("ProfileSubmitServlet: renewal: found serial_num"); - certSerial = new BigInteger(serial); - // usr_origreq evaluator should be used to authorize ownership - // of the cert - } else { - CMS.debug("ProfileSubmitServlet: renewal: serial_num not found, must do ssl client auth"); - // ssl client auth is to be used - // this is not authentication. Just use the cert to search - // for orig request and find the right profile - SSLClientCertProvider sslCCP = new SSLClientCertProvider(request); - X509Certificate[] certs = sslCCP.getClientCertificateChain(); - certSerial = null; - if (certs == null || certs.length == 0) { - CMS.debug("ProfileSubmitServlet: renewal: no ssl client cert chain"); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - return; - } else { // has ssl client cert - CMS.debug("ProfileSubmitServlet: renewal: has ssl client cert chain"); - // shouldn't expect leaf cert to be always at the - // same location - X509Certificate clientCert = null; - for (int i = 0; i < certs.length; i++) { - clientCert = certs[i]; - byte[] extBytes = clientCert.getExtensionValue("2.5.29.19"); - // try to see if this is a leaf cert - // look for BasicConstraint extension - if (extBytes == null) { - // found leaf cert - CMS.debug("ProfileSubmitServlet: renewal: found leaf cert"); - break; - } else { - CMS.debug("ProfileSubmitServlet: renewal: found cert having BasicConstraints ext"); - // it's got BasicConstraints extension - // so it's not likely to be a leaf cert, - // however, check the isCA field regardless - try { - BasicConstraintsExtension bce = - new BasicConstraintsExtension(true, extBytes); - if (bce != null) { - if (!(Boolean) bce.get("is_ca")) { - CMS.debug("ProfileSubmitServlet: renewal: found CA cert in chain"); - break; - } // else found a ca cert, continue - } - } catch (Exception e) { - CMS.debug("ProfileSubmitServlet: renewal: exception:" + - e.toString()); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - return; - } - } - } - if (clientCert == null) { - CMS.debug("ProfileSubmitServlet: renewal: no client cert in chain"); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - return; - } - // convert to java X509 cert interface - try { - byte[] certEncoded = clientCert.getEncoded(); - - clientCert = new X509CertImpl(certEncoded); - } catch (Exception e) { - CMS.debug("ProfileSubmitServlet: renewal: exception:" + e.toString()); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - return; - } - - certSerial = clientCert.getSerialNumber(); - } - } - - CMS.debug("ProfileSubmitServlet: renewal: serial number of cert to renew:" + certSerial.toString()); - - try { - ICertificateRepository certDB = null; - if (authority instanceof ICertificateAuthority) { - certDB = ((ICertificateAuthority) authority).getCertificateRepository(); - } - if (certDB == null) { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - return; - } - ICertRecord rec = certDB.readCertificateRecord(certSerial); - if (rec == null) { - CMS.debug("ProfileSubmitServlet: renewal cert record not found for serial number " - + certSerial.toString()); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - return; - } else { - CMS.debug("ProfileSubmitServlet: renewal cert record found for serial number:" - + certSerial.toString()); - // check to see if the cert is revoked or revoked_expired - if ((rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) - || (rec.getStatus().equals(ICertRecord.STATUS_REVOKED_EXPIRED))) { - CMS.debug("ProfileSubmitServlet: renewal cert found to be revoked. Serial number = " - + certSerial.toString()); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_CA_CANNOT_RENEW_REVOKED_CERT", certSerial.toString())); - outputTemplate(request, response, args); - return; - } - MetaInfo metaInfo = (MetaInfo) rec.get(ICertRecord.ATTR_META_INFO); - // note: CA's internal certs don't have request ids - // so some other way needs to be done - if (metaInfo != null) { - String rid = (String) metaInfo.get(ICertRecord.META_REQUEST_ID); - - if (rid != null) { - origReq = queue.findRequest(new RequestId(rid)); - if (origReq != null) { - CMS.debug("ProfileSubmitServlet: renewal: found original enrollment request id:" + rid); - // debug: print the extData keys - /* - Enumeration<String> en = origReq.getExtDataKeys(); - CMS.debug("ProfileSubmitServlet: renewal: origRequest extdata key print BEGINS"); - while (en.hasMoreElements()) { - String next = (String) en.nextElement(); - CMS.debug("ProfileSubmitServlet: renewal: origRequest extdata key:"+ next); - } - CMS.debug("ProfileSubmitServlet: renewal: origRequest extdata key print ENDS"); - */ - String requestorE = origReq.getExtDataInString("requestor_email"); - CMS.debug("ProfileSubmitServlet: renewal original requestor email=" + requestorE); - profileId = origReq.getExtDataInString("profileId"); - if (profileId != null) - CMS.debug("ProfileSubmitServlet: renewal original profileId=" + profileId); - else { - CMS.debug("ProfileSubmitServlet: renewal original profileId not found"); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - return; - } - origSeqNum = origReq.getExtDataInInteger(IEnrollProfile.REQUEST_SEQ_NUM); - - } else { //if origReq - CMS.debug("ProfileSubmitServlet: renewal original request not found for request id " - + rid); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - return; - } - } else { - CMS.debug("ProfileSubmitServlet: renewal: cert record locating request id in MetaInfo failed for serial number " - + certSerial.toString()); - CMS.debug("ProfileSubmitServlet: renewal: cert may be bootstrapped system cert during installation/configuration - no request record exists"); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR" + ": original request not found")); - outputTemplate(request, response, args); - return; - } - } else { - CMS.debug("ProfileSubmitServlet: renewal: cert record locating MetaInfo failed for serial number " - + certSerial.toString()); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - return; - } - // get orig cert expiration date - CMS.debug("ProfileSubmitServlet: renewal: before getting origNotAfter"); - X509CertImpl origCert = rec.getCertificate(); - origNotAfter = origCert.getNotAfter(); - CMS.debug("ProfileSubmitServlet: renewal: origNotAfter =" + - origNotAfter.toString()); - origSubjectDN = origCert.getSubjectDN().getName(); - CMS.debug("ProfileSubmitServlet: renewal: orig subj dn =" + - origSubjectDN); - } - } catch (Exception e) { - CMS.debug("ProfileSubmitServlet: renewal: exception:" + e.toString()); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - return; - } - } // end isRenewal - - IProfile profile = null; - IProfile renewProfile = null; - - try { - profile = ps.getProfile(profileId); - if (isRenewal) { - // in case of renew, "profile" is the orig profile - // while "renewProfile" is the current profile used for renewal - renewProfile = ps.getProfile(renewProfileId); - } - } catch (EProfileException e) { - if (profile == null) { - CMS.debug("ProfileSubmitServlet: profile not found profileId " + - profileId + " " + e.toString()); - } - if (renewProfile == null) { - CMS.debug("ProfileSubmitServlet: profile not found renewProfileId " + - renewProfileId + " " + e.toString()); - } - } - if (profile == null) { - if (xmlOutput) { - outputError(response, CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); - } else { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_PROFILE_NOT_FOUND", profileId)); - outputTemplate(request, response, args); - } - return; - } - if (isRenewal && (renewProfile == null)) { - if (xmlOutput) { - outputError(response, CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", renewProfileId)); - } else { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_PROFILE_NOT_FOUND", renewProfileId)); - outputTemplate(request, response, args); - } - return; - } - - if (!ps.isProfileEnable(profileId)) { - CMS.debug("ProfileSubmitServlet: Profile " + profileId + - " not enabled"); - if (xmlOutput) { - outputError(response, CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); - } else { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_PROFILE_NOT_FOUND", profileId)); - outputTemplate(request, response, args); - } - if (statsSub != null) { - statsSub.endTiming("enrollment"); - } - return; - } - - if (isRenewal) { - if (!ps.isProfileEnable(renewProfileId)) { - CMS.debug("ProfileSubmitServlet: renewal Profile " + renewProfileId + - " not enabled"); - if (xmlOutput) { - outputError(response, CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", renewProfileId)); - } else { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_PROFILE_NOT_FOUND", renewProfileId)); - outputTemplate(request, response, args); - } - return; - } - } - - IProfileContext ctx = profile.createContext(); - // passing auths into context - IProfileAuthenticator authenticator = null; - IProfileAuthenticator origAuthenticator = null; - - try { - if (isRenewal) { - authenticator = renewProfile.getAuthenticator(); - origAuthenticator = profile.getAuthenticator(); - } else { - authenticator = profile.getAuthenticator(); - } - } catch (EProfileException e) { - // authenticator not installed correctly - CMS.debug("ProfileSubmitServlet: renewal: exception:" + e.toString()); - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - return; - } - if (authenticator == null) { - CMS.debug("ProfileSubmitServlet: authenticator not found"); - } else { - CMS.debug("ProfileSubmitServlet: authenticator " + - authenticator.getName() + " found"); - setCredentialsIntoContext(request, authenticator, ctx); - } - - // for renewal, this will override or add auth info to the profile context - if (isRenewal) { - if (origAuthenticator != null) { - CMS.debug("ProfileSubmitServlet: for renewal, original authenticator " + - origAuthenticator.getName() + " found"); - setCredentialsIntoContext(request, origAuthenticator, ctx); - } else { - CMS.debug("ProfileSubmitServlet: for renewal, original authenticator not found"); - } - } - - CMS.debug("ProfileSubmistServlet: set Inputs into profile Context"); - if (isRenewal) { - // for renewal, input needs to be retrieved from the orig req record - CMS.debug("ProfileSubmitServlet: set original Inputs into profile Context"); - setInputsIntoContext(origReq, profile, ctx, locale); - ctx.set(IEnrollProfile.CTX_RENEWAL, "true"); - ctx.set("renewProfileId", renewProfileId); - ctx.set(IEnrollProfile.CTX_RENEWAL_SEQ_NUM, origSeqNum.toString()); - } else { - setInputsIntoContext(request, profile, ctx); - } - - // before creating the request, authenticate the request - - IAuthToken authToken = null; - - // for ssl authentication; pass in servlet for retrieving - // ssl client certificates - SessionContext context = SessionContext.getContext(); - - // insert profile context so that input parameter can be retrieved - context.put("profileContext", ctx); - context.put("sslClientCertProvider", - new SSLClientCertProvider(request)); - CMS.debug("ProfileSubmitServlet: set sslClientCertProvider"); - if ((isRenewal == true) && (origSubjectDN != null)) - context.put("origSubjectDN", origSubjectDN); - if (statsSub != null) { - statsSub.startTiming("profile_authentication"); - } - - if (authenticator != null) { - - CMS.debug("ProfileSubmitServlet: authentication required."); - String uid_cred = "Unidentified"; - String uid_attempted_cred = "Unidentified"; - Enumeration<String> authIds = authenticator.getValueNames(); - //Attempt to possibly fetch attemped uid, may not always be available. - if (authIds != null) { - while (authIds.hasMoreElements()) { - String authName = authIds.nextElement(); - String value = request.getParameter(authName); - if (value != null) { - if (authName.equals("uid")) { - uid_attempted_cred = value; - } - } - } - } - - String authSubjectID = auditSubjectID(); - - String authMgrID = authenticator.getName(); - String auditMessage = null; - try { - if (isRenewal) { - CMS.debug("ProfileSubmitServlet: renewal authenticate begins"); - authToken = authenticate(authenticator, request, origReq, context); - CMS.debug("ProfileSubmitServlet: renewal authenticate ends"); - } else { - authToken = authenticate(authenticator, request); - } - } catch (EBaseException e) { - CMS.debug("ProfileSubmitServlet: authentication error " + - e.toString()); - // authentication error - if (xmlOutput) { - outputError(response, CMS.getUserMessage(locale, "CMS_AUTHENTICATION_ERROR")); - } else { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_AUTHENTICATION_ERROR")); - outputTemplate(request, response, args); - } - if (statsSub != null) { - statsSub.endTiming("authentication"); - } - if (statsSub != null) { - statsSub.endTiming("enrollment"); - } - - //audit log our authentication failure - - authSubjectID += " : " + uid_cred; - auditMessage = CMS.getLogMessage( - LOGGING_SIGNED_AUDIT_AUTH_FAIL, - authSubjectID, - ILogger.FAILURE, - authMgrID, - uid_attempted_cred); - audit(auditMessage); - - return; - } - - //Log successful authentication - - //Attempt to get uid from authToken, most tokens respond to the "uid" cred. - uid_cred = authToken.getInString("uid"); - - if (uid_cred == null || uid_cred.length() == 0) { - uid_cred = "Unidentified"; - } - - authSubjectID = authSubjectID + " : " + uid_cred; - - // store a message in the signed audit log file - auditMessage = CMS.getLogMessage( - LOGGING_SIGNED_AUDIT_AUTH_SUCCESS, - authSubjectID, - ILogger.SUCCESS, - authMgrID); - - audit(auditMessage); - - } - if (statsSub != null) { - statsSub.endTiming("profile_authentication"); - } - - // authentication success - if (authToken != null) { - CMS.debug("ProfileSubmitServlet authToken not null"); - // do profile authorization - String acl = null; - if (isRenewal) - acl = renewProfile.getAuthzAcl(); - else - acl = profile.getAuthzAcl(); - CMS.debug("ProfileSubmitServlet: authz using acl: " + acl); - if (acl != null && acl.length() > 0) { - try { - String resource = profileId + ".authz.acl"; - authorize(mAclMethod, resource, authToken, acl); - } catch (Exception e) { - CMS.debug("ProfileSubmitServlet authorize: " + e.toString()); - if (xmlOutput) { - outputError(response, CMS.getUserMessage(locale, - "CMS_AUTHORIZATION_ERROR")); - } else { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_AUTHORIZATION_ERROR")); - outputTemplate(request, response, args); - } - - return; - } - } - } - - IRequest reqs[] = null; - - if (statsSub != null) { - statsSub.startTiming("request_population"); - } - /////////////////////////////////////////////// - // create request - /////////////////////////////////////////////// - try { - reqs = profile.createRequests(ctx, locale); - } catch (EProfileException e) { - CMS.debug(e); - CMS.debug("ProfileSubmitServlet: createRequests " + e.toString()); - if (xmlOutput) { - outputError(response, e.toString()); - } else { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, e.toString()); - outputTemplate(request, response, args); - } - if (statsSub != null) { - statsSub.endTiming("request_population"); - statsSub.endTiming("enrollment"); - } - return; - } catch (Throwable e) { - CMS.debug(e); - CMS.debug("ProfileSubmitServlet: createRequests " + e.toString()); - if (xmlOutput) { - outputError(response, CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); - } else { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - } - if (statsSub != null) { - statsSub.endTiming("request_population"); - statsSub.endTiming("enrollment"); - } - return; - } - - String errorCode = null; - String errorReason = null; - - /////////////////////////////////////////////// - // populate request - /////////////////////////////////////////////// - for (int k = 0; k < reqs.length; k++) { - boolean fromRA = false; - String uid = ""; - - // adding parameters to request - if (isRenewal) { - setInputsIntoRequest(origReq, profile, reqs[k], locale); - // set orig expiration date to be used in Validity constraint - reqs[k].setExtData("origNotAfter", - BigInteger.valueOf(origNotAfter.getTime())); - // set subjectDN to be used in subject name default - reqs[k].setExtData(IProfileAuthenticator.AUTHENTICATED_NAME, origSubjectDN); - // set request type - reqs[k].setRequestType("renewal"); - } else - setInputsIntoRequest(request, profile, reqs[k]); - - // serial auth token into request - if (authToken != null) { - Enumeration<String> tokenNames = authToken.getElements(); - while (tokenNames.hasMoreElements()) { - String tokenName = tokenNames.nextElement(); - String[] tokenVals = authToken.getInStringArray(tokenName); - if (tokenVals != null) { - for (int i = 0; i < tokenVals.length; i++) { - reqs[k].setExtData(ARG_AUTH_TOKEN + "." + - tokenName + "[" + i + "]", tokenVals[i]); - } - } else { - String tokenVal = authToken.getInString(tokenName); - if (tokenVal != null) { - reqs[k].setExtData(ARG_AUTH_TOKEN + "." + tokenName, - tokenVal); - // if RA agent, auto assign the request - if (tokenName.equals("uid")) - uid = tokenVal; - if (tokenName.equals("group") && - tokenVal.equals("Registration Manager Agents")) { - fromRA = true; - } - } - } - } - } - - if (fromRA) { - CMS.debug("ProfileSubmitServlet: request from RA: " + uid); - reqs[k].setExtData(ARG_REQUEST_OWNER, uid); - } - - // put profile framework parameters into the request - reqs[k].setExtData(ARG_PROFILE, "true"); - reqs[k].setExtData(ARG_PROFILE_ID, profileId); - if (isRenewal) - reqs[k].setExtData(ARG_RENEWAL_PROFILE_ID, request.getParameter("profileId")); - reqs[k].setExtData(ARG_PROFILE_APPROVED_BY, profile.getApprovedBy()); - String setId = profile.getPolicySetId(reqs[k]); - - if (setId == null) { - // no profile set found - CMS.debug("ProfileSubmitServlet: no profile policy set found"); - if (xmlOutput) { - outputError(response, FAILED, CMS.getUserMessage("CMS_PROFILE_NO_POLICY_SET_FOUND"), - reqs[k].getRequestId().toString()); - } else { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, - CMS.getUserMessage("CMS_PROFILE_NO_POLICY_SET_FOUND")); - outputTemplate(request, response, args); - } - if (statsSub != null) { - statsSub.endTiming("request_population"); - statsSub.endTiming("enrollment"); - } - return; - } - - CMS.debug("ProfileSubmitServlet profileSetid=" + setId); - reqs[k].setExtData(ARG_PROFILE_SET_ID, setId); - reqs[k].setExtData(ARG_PROFILE_REMOTE_HOST, request.getRemoteHost()); - reqs[k].setExtData(ARG_PROFILE_REMOTE_ADDR, request.getRemoteAddr()); - - CMS.debug("ProfileSubmitServlet: request " + - reqs[k].getRequestId().toString()); - - try { - CMS.debug("ProfileSubmitServlet: populating request inputs"); - // give authenticator a chance to populate the request - if (authenticator != null) { - authenticator.populate(authToken, reqs[k]); - } - profile.populateInput(ctx, reqs[k]); - profile.populate(reqs[k]); - } catch (EProfileException e) { - CMS.debug("ProfileSubmitServlet: populate " + e.toString()); - if (xmlOutput) { - outputError(response, FAILED, e.toString(), reqs[k].getRequestId().toString()); - } else { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, e.toString()); - outputTemplate(request, response, args); - } - if (statsSub != null) { - statsSub.endTiming("request_population"); - statsSub.endTiming("enrollment"); - } - return; - } catch (Throwable e) { - CMS.debug("ProfileSubmitServlet: populate " + e.toString()); - // throw new IOException("Profile " + profileId + - // " cannot populate"); - if (xmlOutput) { - outputError(response, FAILED, CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR"), - reqs[k].getRequestId().toString()); - } else { - args.set(ARG_ERROR_CODE, "1"); - args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR")); - outputTemplate(request, response, args); - } - if (statsSub != null) { - statsSub.endTiming("request_population"); - statsSub.endTiming("enrollment"); - } - return; - } - } - if (statsSub != null) { - statsSub.endTiming("request_population"); - } - - String auditMessage = null; - String auditSubjectID = auditSubjectID(); - String auditRequesterID = ILogger.UNIDENTIFIED; - String auditInfoCertValue = ILogger.SIGNED_AUDIT_EMPTY_VALUE; - - try { - /////////////////////////////////////////////// - // submit request - /////////////////////////////////////////////// - String requestIds = ""; // deliminated with double space - for (int k = 0; k < reqs.length; k++) { - try { - // reset the "auditRequesterID" - auditRequesterID = auditRequesterID(reqs[k]); - - // print request debug - if (reqs[k] != null) { - requestIds += " " + reqs[k].getRequestId().toString(); - Enumeration<String> reqKeys = reqs[k].getExtDataKeys(); - while (reqKeys.hasMoreElements()) { - String reqKey = reqKeys.nextElement(); - String reqVal = reqs[k].getExtDataInString(reqKey); - if (reqVal != null) { - CMS.debug("ProfileSubmitServlet: key=$request." + reqKey + "$ value=" + reqVal); - } - } - } - - profile.submit(authToken, reqs[k]); - reqs[k].setRequestStatus(RequestStatus.COMPLETE); - - // reset the "auditInfoCertValue" - auditInfoCertValue = auditInfoCertValue(reqs[k]); - - if (auditInfoCertValue != null) { - if (!(auditInfoCertValue.equals( - ILogger.SIGNED_AUDIT_EMPTY_VALUE))) { - // store a message in the signed audit log file - auditMessage = CMS.getLogMessage( - LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, - auditSubjectID, - ILogger.SUCCESS, - auditRequesterID, - ILogger.SIGNED_AUDIT_ACCEPTANCE, - auditInfoCertValue); - - audit(auditMessage); - } - } - } catch (EDeferException e) { - // return defer message to the user - reqs[k].setRequestStatus(RequestStatus.PENDING); - // need to notify - INotify notify = profile.getRequestQueue().getPendingNotify(); - if (notify != null) { - notify.notify(reqs[k]); - } - - CMS.debug("ProfileSubmitServlet: submit " + e.toString()); - errorCode = "2"; - errorReason = CMS.getUserMessage(locale, - "CMS_PROFILE_DEFERRED", - e.toString()); - } catch (ERejectException e) { - // return error to the user - reqs[k].setRequestStatus(RequestStatus.REJECTED); - CMS.debug("ProfileSubmitServlet: submit " + e.toString()); - errorCode = "3"; - errorReason = CMS.getUserMessage(locale, - "CMS_PROFILE_REJECTED", - e.toString()); - } catch (Throwable e) { - // return error to the user - CMS.debug("ProfileSubmitServlet: submit " + e.toString()); - errorCode = "1"; - errorReason = CMS.getUserMessage(locale, - "CMS_INTERNAL_ERROR"); - } - - try { - if (errorCode == null) { - profile.getRequestQueue().markAsServiced(reqs[k]); - } else { - profile.getRequestQueue().updateRequest(reqs[k]); - } - } catch (EBaseException e) { - CMS.debug("ProfileSubmitServlet: updateRequest " + - e.toString()); - } - - if (errorCode != null) { - if (errorCode.equals("1")) { - // store a message in the signed audit log file - auditMessage = CMS.getLogMessage( - LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, - auditSubjectID, - ILogger.FAILURE, - auditRequesterID, - ILogger.SIGNED_AUDIT_REJECTION, - errorReason); - - audit(auditMessage); - } else if (errorCode.equals("2")) { - // do NOT store a message in the signed audit log file - // as this errorCode indicates that a process has been - // deferred for manual acceptance/cancellation/rejection - } else if (errorCode.equals("3")) { - // store a message in the signed audit log file - auditMessage = CMS.getLogMessage( - LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, - auditSubjectID, - ILogger.FAILURE, - auditRequesterID, - ILogger.SIGNED_AUDIT_REJECTION, - errorReason); - - audit(auditMessage); - } - } - } - - if (errorCode != null) { - if (xmlOutput) { - // when errorCode is not null, requestIds should have >=1 - outputError(response, errorCode, errorReason, requestIds); - } else { - ArgList requestlist = new ArgList(); - - for (int k = 0; k < reqs.length; k++) { - ArgSet requestset = new ArgSet(); - - requestset.set(ARG_REQUEST_ID, - reqs[k].getRequestId().toString()); - requestlist.add(requestset); - } - args.set(ARG_REQUEST_LIST, requestlist); - args.set(ARG_ERROR_CODE, errorCode); - args.set(ARG_ERROR_REASON, errorReason); - outputTemplate(request, response, args); - } - if (statsSub != null) { - statsSub.endTiming("enrollment"); - } - return; - } - - /////////////////////////////////////////////// - // output output list - /////////////////////////////////////////////// - if (xmlOutput) { - xmlOutput(response, profile, locale, reqs); - } else { - ArgList outputlist = new ArgList(); - for (int k = 0; k < reqs.length; k++) { - - setOutputIntoArgs(profile, outputlist, locale, reqs[k]); - args.set(ARG_OUTPUT_LIST, outputlist); - } - - CMS.debug("ProfileSubmitServlet: done serving"); - - ArgList requestlist = new ArgList(); - - for (int k = 0; k < reqs.length; k++) { - ArgSet requestset = new ArgSet(); - - requestset.set(ARG_REQUEST_ID, - reqs[k].getRequestId().toString()); - requestlist.add(requestset); - } - args.set(ARG_REQUEST_LIST, requestlist); - args.set(ARG_ERROR_CODE, "0"); - args.set(ARG_ERROR_REASON, ""); - - outputTemplate(request, response, args); - } - } catch (EBaseException eAudit1) { - // store a message in the signed audit log file - // (automated cert request processed - "rejected") - auditMessage = CMS.getLogMessage( - LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, - auditSubjectID, - ILogger.FAILURE, - auditRequesterID, - ILogger.SIGNED_AUDIT_REJECTION, - SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[0]); - - audit(auditMessage); - - if (statsSub != null) { - statsSub.endTiming("enrollment"); - } - throw eAudit1; - } finally { - SessionContext.releaseContext(); - } - if (statsSub != null) { - statsSub.endTiming("enrollment"); - } + return xmlOutput; } private void xmlOutput(HttpServletResponse httpResp, IProfile profile, Locale locale, IRequest[] reqs) { @@ -1535,96 +344,4 @@ public class ProfileSubmitServlet extends ProfileServlet { } } - /** - * Signed Audit Log Requester ID - * - * This method is called to obtain the "RequesterID" for - * a signed audit log message. - * <P> - * - * @param request the actual request - * @return id string containing the signed audit log message RequesterID - */ - private String auditRequesterID(IRequest request) { - // if no signed audit object exists, bail - if (mSignedAuditLogger == null) { - return null; - } - - String requesterID = ILogger.UNIDENTIFIED; - - if (request != null) { - // overwrite "requesterID" if and only if "id" != null - String id = request.getRequestId().toString(); - - if (id != null) { - requesterID = id.trim(); - } - } - - return requesterID; - } - - /** - * Signed Audit Log Info Certificate Value - * - * This method is called to obtain the certificate from the passed in - * "X509CertImpl" for a signed audit log message. - * <P> - * - * @param request request containing an X509CertImpl - * @return cert string containing the certificate - */ - private String auditInfoCertValue(IRequest request) { - // if no signed audit object exists, bail - if (mSignedAuditLogger == null) { - return null; - } - - X509CertImpl x509cert = request.getExtDataInCert( - IEnrollProfile.REQUEST_ISSUED_CERT); - - if (x509cert == null) { - return ILogger.SIGNED_AUDIT_EMPTY_VALUE; - } - - byte rawData[] = null; - - try { - rawData = x509cert.getEncoded(); - } catch (CertificateEncodingException e) { - return ILogger.SIGNED_AUDIT_EMPTY_VALUE; - } - - String cert = null; - - // convert "rawData" into "base64Data" - if (rawData != null) { - String base64Data = null; - - base64Data = Utils.base64encode(rawData).trim(); - - // extract all line separators from the "base64Data" - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < base64Data.length(); i++) { - if (!Character.isWhitespace(base64Data.charAt(i))) { - sb.append(base64Data.charAt(i)); - - } - } - cert = sb.toString(); - } - - if (cert != null) { - cert = cert.trim(); - - if (cert.equals("")) { - return ILogger.SIGNED_AUDIT_EMPTY_VALUE; - } else { - return cert; - } - } else { - return ILogger.SIGNED_AUDIT_EMPTY_VALUE; - } - } } diff --git a/base/common/src/com/netscape/cms/servlet/profile/model/PolicyConstraint.java b/base/common/src/com/netscape/cms/servlet/profile/model/PolicyConstraint.java new file mode 100644 index 000000000..588431a83 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/model/PolicyConstraint.java @@ -0,0 +1,73 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class PolicyConstraint { + @XmlAttribute(name="id") + private String name; + + @XmlElement(name="description") + private String text; + + @XmlElement(name = "constraint") + private List<PolicyConstraintValue> constraints = new ArrayList<PolicyConstraintValue>(); + + public PolicyConstraint() { + // required for jaxb + } + + public void addConstraint(PolicyConstraintValue constraint) { + constraints.add(constraint); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public List<PolicyConstraintValue> getConstraints() { + return constraints; + } + + public void setConstraints(List<PolicyConstraintValue> constraints) { + this.constraints = constraints; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/profile/model/PolicyConstraintFactory.java b/base/common/src/com/netscape/cms/servlet/profile/model/PolicyConstraintFactory.java new file mode 100644 index 000000000..bd361a752 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/model/PolicyConstraintFactory.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) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile.model; + +import java.util.Enumeration; +import java.util.Locale; + +import com.netscape.certsrv.profile.IPolicyConstraint; +import com.netscape.certsrv.property.Descriptor; + +public class PolicyConstraintFactory { + + public static PolicyConstraint create(Locale locale, IPolicyConstraint cons) { + PolicyConstraint ret = new PolicyConstraint(); + ret.setName(cons.getName(locale)); + ret.setText(cons.getText(locale)); + + Enumeration<String> conNames = cons.getConfigNames(); + while (conNames.hasMoreElements()) { + String conName = conNames.nextElement(); + PolicyConstraintValue dataVal = + new PolicyConstraintValue(conName, (Descriptor) cons.getConfigDescriptor(locale, conName)); + ret.addConstraint(dataVal); + } + return ret; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/profile/model/PolicyConstraintValue.java b/base/common/src/com/netscape/cms/servlet/profile/model/PolicyConstraintValue.java new file mode 100644 index 000000000..7b60e7ea6 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/model/PolicyConstraintValue.java @@ -0,0 +1,61 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile.model; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import com.netscape.certsrv.property.Descriptor; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class PolicyConstraintValue { + @XmlAttribute(name="id") + private String name; + + @XmlElement + private Descriptor descriptor; + + public PolicyConstraintValue() { + // required for jax-b + } + + public PolicyConstraintValue(String name, Descriptor descriptor) { + this.name = name; + this.descriptor = descriptor; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Descriptor getDescriptor() { + return descriptor; + } + + public void setDescriptor(Descriptor descriptor) { + this.descriptor = descriptor; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/profile/model/PolicyDefault.java b/base/common/src/com/netscape/cms/servlet/profile/model/PolicyDefault.java new file mode 100644 index 000000000..2c66fc9dc --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/model/PolicyDefault.java @@ -0,0 +1,73 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class PolicyDefault { + @XmlAttribute(name="id") + private String name; + + @XmlElement(name="description") + private String text; + + @XmlElement(name="policyAttribute") + private List<ProfileAttribute> attributes = new ArrayList<ProfileAttribute>(); + + public PolicyDefault() { + // required for jaxb + } + + public void addAttribute(ProfileAttribute attr) { + attributes.add(attr); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public List<ProfileAttribute> getAttributes() { + return attributes; + } + + public void setAttributes(List<ProfileAttribute> attributes) { + this.attributes = attributes; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/profile/model/PolicyDefaultFactory.java b/base/common/src/com/netscape/cms/servlet/profile/model/PolicyDefaultFactory.java new file mode 100644 index 000000000..6b9379f0b --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/model/PolicyDefaultFactory.java @@ -0,0 +1,65 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile.model; + +import java.util.Enumeration; +import java.util.Locale; + +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.profile.IPolicyDefault; +import com.netscape.certsrv.property.Descriptor; +import com.netscape.certsrv.property.EPropertyException; +import com.netscape.certsrv.request.IRequest; + +public class PolicyDefaultFactory { + + public static PolicyDefault create(IRequest request, Locale locale, IPolicyDefault def) throws EPropertyException { + PolicyDefault ret = new PolicyDefault(); + ret.setName(def.getName(locale)); + ret.setText(def.getText(locale)); + + Enumeration<String> defNames = def.getValueNames(); + while (defNames.hasMoreElements()) { + String defName = defNames.nextElement(); + ProfileAttribute attr = new ProfileAttribute( + defName, + def.getValue(defName, locale, request), + (Descriptor) def.getValueDescriptor(locale, defName)); + ret.addAttribute(attr); + } + return ret; + } + + public static PolicyDefault create(IArgBlock params, Locale locale, IPolicyDefault def) throws EPropertyException { + PolicyDefault ret = new PolicyDefault(); + ret.setName(def.getName(locale)); + ret.setText(def.getText(locale)); + + Enumeration<String> defNames = def.getValueNames(); + while (defNames.hasMoreElements()) { + String defName = defNames.nextElement(); + ProfileAttribute attr = new ProfileAttribute( + defName, + params.getValueAsString(defName, ""), + (Descriptor) def.getValueDescriptor(locale, defName)); + ret.addAttribute(attr); + } + return ret; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/profile/model/ProfileAttribute.java b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileAttribute.java new file mode 100644 index 000000000..616c0695d --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileAttribute.java @@ -0,0 +1,80 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile.model; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import com.netscape.certsrv.property.Descriptor; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class ProfileAttribute { + + @XmlAttribute + private String name; + + @XmlElement + private String value; + + @XmlElement + private Descriptor descriptor; + + public ProfileAttribute() { + // required for jax-b + } + + public ProfileAttribute(String name, String value, Descriptor descriptor) { + this.name = name; + this.value = value; + this.descriptor = descriptor; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Descriptor getDescriptor() { + return descriptor; + } + + public void setDescriptor(Descriptor descriptor) { + this.descriptor = descriptor; + } + + @Override + public String toString() { + return "PolicyAttribute [name=" + name + ", value=" + value + ", descriptor=" + descriptor + "]"; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/profile/model/ProfileData.java b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileData.java index 22a59c470..7f7f26b29 100644 --- a/base/common/src/com/netscape/cms/servlet/profile/model/ProfileData.java +++ b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileData.java @@ -41,6 +41,7 @@ public class ProfileData { @XmlElement protected String id; + @XmlElement protected String name; diff --git a/base/common/src/com/netscape/cms/servlet/profile/model/ProfileDataInfo.java b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileDataInfo.java index 63f005b54..d5083c7a4 100644 --- a/base/common/src/com/netscape/cms/servlet/profile/model/ProfileDataInfo.java +++ b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileDataInfo.java @@ -1,5 +1,3 @@ -package com.netscape.cms.servlet.profile.model; - //--- 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 @@ -17,18 +15,16 @@ package com.netscape.cms.servlet.profile.model; //(C) 2011 Red Hat, Inc. //All rights reserved. //--- END COPYRIGHT BLOCK --- -/** - * - */ +package com.netscape.cms.servlet.profile.model; import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlAccessorType; /** * @author alee - * + * */ @XmlRootElement(name = "ProfileDataInfo") @XmlAccessorType(XmlAccessType.FIELD) diff --git a/base/common/src/com/netscape/cms/servlet/profile/model/ProfileInput.java b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileInput.java index a0aea9fd4..631a013cc 100644 --- a/base/common/src/com/netscape/cms/servlet/profile/model/ProfileInput.java +++ b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileInput.java @@ -30,12 +30,17 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; public class ProfileInput { + public ProfileInput() { + // required for jaxb + } + @XmlElement public String getInputId() { return inputId; } private String inputId; + @XmlJavaTypeAdapter(InputAttrsAdapter.class) public Map<String, String> InputAttrs = new LinkedHashMap<String, String>(); diff --git a/base/common/src/com/netscape/cms/servlet/profile/model/ProfileInputFactory.java b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileInputFactory.java new file mode 100644 index 000000000..67d3e9a2c --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileInputFactory.java @@ -0,0 +1,40 @@ +package com.netscape.cms.servlet.profile.model; + +import java.util.Enumeration; +import java.util.Locale; + +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.profile.EProfileException; +import com.netscape.certsrv.profile.IProfileInput; +import com.netscape.certsrv.request.IRequest; + +public class ProfileInputFactory { + + public static ProfileInput create(IProfileInput input, IRequest request, Locale locale) throws EProfileException { + ProfileInput ret = new ProfileInput(); + ret.setInputId(input.getName(locale)); + Enumeration<String> names = input.getValueNames(); + while (names.hasMoreElements()) { + String name = names.nextElement(); + String value = input.getValue(name, locale, request); + if (value != null) { + ret.setInputAttr(name, value); + } + } + return ret; + } + + public static ProfileInput create(IProfileInput input, IArgBlock params, Locale locale) throws EProfileException { + ProfileInput ret = new ProfileInput(); + ret.setInputId(input.getName(locale)); + Enumeration<String> names = input.getValueNames(); + while (names.hasMoreElements()) { + String name = names.nextElement(); + String value = params.getValueAsString(name, null); + if (value != null) { + ret.setInputAttr(name, value); + } + } + return ret; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/profile/model/ProfileOutput.java b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileOutput.java new file mode 100644 index 000000000..f27db4101 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileOutput.java @@ -0,0 +1,84 @@ +// --- 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.profile.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class ProfileOutput { + + public ProfileOutput() { + // required for jaxb + } + + @XmlElement + private String outputId; + + @XmlElement(name = "attributes") + private List<ProfileAttribute> attrs = new ArrayList<ProfileAttribute>(); + + @XmlElement + private String name; + + @XmlElement + private String text; + + public String getOutputId() { + return outputId; + } + + public void setOutputId(String OutputId) { + this.outputId = OutputId; + } + + public List<ProfileAttribute> getAttrs() { + return attrs; + } + + public void setAttrs(List<ProfileAttribute> attrs) { + this.attrs = attrs; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public void addAttribute(ProfileAttribute attr) { + attrs.add(attr); + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/profile/model/ProfileOutputFactory.java b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileOutputFactory.java new file mode 100644 index 000000000..93bbaa2c5 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileOutputFactory.java @@ -0,0 +1,47 @@ +//--- BEGIN COPYRIGHT BLOCK --- +//This program is free software; you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation; version 2 of the License. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License along +//with this program; if not, write to the Free Software Foundation, Inc., +//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//(C) 2012 Red Hat, Inc. +//All rights reserved. +//--- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile.model; + +import java.util.Enumeration; +import java.util.Locale; + +import com.netscape.certsrv.profile.EProfileException; +import com.netscape.certsrv.profile.IProfileOutput; +import com.netscape.certsrv.property.Descriptor; +import com.netscape.certsrv.request.IRequest; + +public class ProfileOutputFactory { + + public static ProfileOutput create(IProfileOutput output, IRequest request, Locale locale) throws EProfileException { + ProfileOutput ret = new ProfileOutput(); + ret.setName(output.getName(locale)); + ret.setText(output.getText(locale)); + + Enumeration<String> attrNames = output.getValueNames(); + while (attrNames.hasMoreElements()) { + String attrName = attrNames.nextElement(); + ProfileAttribute attr = new ProfileAttribute( + attrName, + output.getValue(attrName, locale, request), + (Descriptor) output.getValueDescriptor(locale, attrName)); + ret.addAttribute(attr); + } + return ret; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/profile/model/ProfilePolicy.java b/base/common/src/com/netscape/cms/servlet/profile/model/ProfilePolicy.java new file mode 100644 index 000000000..a24f93619 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/model/ProfilePolicy.java @@ -0,0 +1,82 @@ +//--- BEGIN COPYRIGHT BLOCK --- +//This program is free software; you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation; version 2 of the License. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License along +//with this program; if not, write to the Free Software Foundation, Inc., +//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//(C) 2012 Red Hat, Inc. +//All rights reserved. +//--- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile.model; + +import java.io.ByteArrayOutputStream; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class ProfilePolicy { + @XmlAttribute + private String id = null; + + @XmlElement + private PolicyDefault def = null; + + @XmlElement + private PolicyConstraint constraint = null; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public PolicyDefault getDef() { + return def; + } + + public void setDef(PolicyDefault def) { + this.def = def; + } + + public PolicyConstraint getConstraint() { + return constraint; + } + + public void setConstraint(PolicyConstraint constraint) { + this.constraint = constraint; + } + + public String toString() { + try { + JAXBContext context = JAXBContext.newInstance(ProfilePolicy.class); + Marshaller marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + + marshaller.marshal(this, stream); + return stream.toString(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/profile/model/ProfilePolicySet.java b/base/common/src/com/netscape/cms/servlet/profile/model/ProfilePolicySet.java new file mode 100644 index 000000000..784f5670d --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/model/ProfilePolicySet.java @@ -0,0 +1,50 @@ +//--- BEGIN COPYRIGHT BLOCK --- +//This program is free software; you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation; version 2 of the License. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License along +//with this program; if not, write to the Free Software Foundation, Inc., +//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//(C) 2012 Red Hat, Inc. +//All rights reserved. +//--- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class ProfilePolicySet { + @XmlElement + protected List<ProfilePolicy> policies = new ArrayList<ProfilePolicy>(); + + public List<ProfilePolicy> getPolicies() { + return policies; + } + + public void setPolicies(List<ProfilePolicy> policies) { + this.policies = policies; + } + + public void addPolicy(ProfilePolicy policy) { + policies.add(policy); + } + + public void removePolicy(ProfilePolicy policy) { + policies.remove(policy); + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/request/CertRequestResource.java b/base/common/src/com/netscape/cms/servlet/request/CertRequestResource.java index 5dc97650d..7bb23dbd5 100644 --- a/base/common/src/com/netscape/cms/servlet/request/CertRequestResource.java +++ b/base/common/src/com/netscape/cms/servlet/request/CertRequestResource.java @@ -27,7 +27,9 @@ 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.AgentEnrollmentRequestData; import com.netscape.cms.servlet.request.model.CertRequestInfo; +import com.netscape.cms.servlet.request.model.CertRequestInfos; import com.netscape.cms.servlet.request.model.EnrollmentRequestData; @Path("/certrequest") @@ -41,29 +43,56 @@ public interface CertRequestResource { @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) public CertRequestInfo getRequestInfo(@PathParam("id") RequestId id); + @GET + @Path("{id}/agentView") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) + public AgentEnrollmentRequestData reviewRequest(@PathParam("id") RequestId id); + // Enrollment - used to test integration with a browser @POST @Path("enroll") @Produces({ MediaType.TEXT_XML }) @Consumes({ MediaType.APPLICATION_FORM_URLENCODED }) - public CertRequestInfo enrollCert(MultivaluedMap<String, String> form); + public CertRequestInfos enrollCert(MultivaluedMap<String, String> form); @POST @Path("enroll") @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) - public CertRequestInfo enrollCert(EnrollmentRequestData data); + public CertRequestInfos enrollCert(EnrollmentRequestData data); @POST - @Path("approve/{id}") - public void approveRequest(@PathParam("id") RequestId id); + @Path("{id}/approve") + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public void approveRequest(@PathParam("id") RequestId id, AgentEnrollmentRequestData data); @POST - @Path("reject/{id}") - public void rejectRequest(@PathParam("id") RequestId id); + @Path("{id}/reject") + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public void rejectRequest(@PathParam("id") RequestId id, AgentEnrollmentRequestData data); @POST - @Path("cancel/{id}") - public void cancelRequest(@PathParam("id") RequestId id); + @Path("{id}/cancel") + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public void cancelRequest(@PathParam("id") RequestId id, AgentEnrollmentRequestData data); + + @POST + @Path("{id}/update") + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public void updateRequest(@PathParam("id") RequestId id, AgentEnrollmentRequestData data); + @POST + @Path("{id}/validate") + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public void validateRequest(@PathParam("id") RequestId id, AgentEnrollmentRequestData data); + + @POST + @Path("{id}/unassign") + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public void unassignRequest(@PathParam("id") RequestId id, AgentEnrollmentRequestData data); + + @POST + @Path("{id}/assign") + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public void assignRequest(@PathParam("id") RequestId id, AgentEnrollmentRequestData data); } diff --git a/base/common/src/com/netscape/cms/servlet/request/CertRequestResourceService.java b/base/common/src/com/netscape/cms/servlet/request/CertRequestResourceService.java index 40f57a7a7..b31d9961d 100644 --- a/base/common/src/com/netscape/cms/servlet/request/CertRequestResourceService.java +++ b/base/common/src/com/netscape/cms/servlet/request/CertRequestResourceService.java @@ -18,15 +18,27 @@ package com.netscape.cms.servlet.request; +import javax.ws.rs.PathParam; import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.EAuthException; +import com.netscape.certsrv.authorization.EAuthzException; +import com.netscape.certsrv.base.BadRequestDataException; import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.profile.EDeferException; +import com.netscape.certsrv.profile.EProfileException; +import com.netscape.certsrv.profile.ERejectException; +import com.netscape.certsrv.property.EPropertyException; import com.netscape.certsrv.request.RequestId; import com.netscape.cms.servlet.base.BadRequestException; import com.netscape.cms.servlet.base.CMSException; import com.netscape.cms.servlet.base.CMSResourceService; +import com.netscape.cms.servlet.request.model.AgentEnrollmentRequestData; import com.netscape.cms.servlet.request.model.CertRequestDAO; import com.netscape.cms.servlet.request.model.CertRequestInfo; +import com.netscape.cms.servlet.request.model.CertRequestInfos; import com.netscape.cms.servlet.request.model.EnrollmentRequestData; /** @@ -60,51 +72,119 @@ public class CertRequestResourceService extends CMSResourceService implements Ce } // Enrollment - used to test integration with a browser - public CertRequestInfo enrollCert(MultivaluedMap<String, String> form) { + public CertRequestInfos enrollCert(MultivaluedMap<String, String> form) { EnrollmentRequestData data = new EnrollmentRequestData(form); return enrollCert(data); } - public CertRequestInfo enrollCert(EnrollmentRequestData data) { - + public CertRequestInfos enrollCert(EnrollmentRequestData data) { + CertRequestInfos infos; if (data == null) { throw new BadRequestException("Bad data input into CertRequestResourceService.enrollCert!"); } CertRequestDAO dao = new CertRequestDAO(); try { - dao.submitRequest(data, uriInfo); + infos = dao.submitRequest(data, servletRequest, uriInfo, getLocale()); + } catch (EAuthException e) { + CMS.debug("enrollCert: authentication failed: " + e); + throw new CMSException(Response.Status.UNAUTHORIZED, e.toString()); + } catch (EAuthzException e) { + CMS.debug("enrollCert: authorization failed: " + e); + throw new CMSException(Response.Status.UNAUTHORIZED, e.toString()); + } catch (BadRequestDataException e) { + CMS.debug("enrollCert: bad request data: " + e); + throw new CMSException(Response.Status.BAD_REQUEST, e.toString()); } catch (EBaseException e) { - throw new CMSException("Problem enrolling cert in CertRequestResource.enrollCert!"); + throw new CMSException(e.toString()); } - //TODO implement - throw new CMSException("CertRequestResourceService.enrollCert not implemented!"); + return infos; } - public void approveRequest(RequestId id) { - if (id == null) { - throw new BadRequestException("Bad data input in CertRequestResourceService.approveRequest!"); - } - //TODO implement - throw new CMSException("Problem approving request in CertRequestResource.approveRequest!"); + public void approveRequest(RequestId id, AgentEnrollmentRequestData data) { + changeRequestState(id, data, "approve"); } - public void rejectRequest(RequestId id) { - if (id == null) { - throw new BadRequestException("Bad data input into CertRequestResourceService.rejectRequest!"); - } - //TODO implement + public void rejectRequest(RequestId id, AgentEnrollmentRequestData data) { + changeRequestState(id, data, "reject"); + } - throw new CMSException("Problem rejecting request in CertRequestResource.rejectRequest!"); + public void cancelRequest(RequestId id, AgentEnrollmentRequestData data) { + changeRequestState(id, data, "cancel"); + } + public void updateRequest(RequestId id, AgentEnrollmentRequestData data) { + changeRequestState(id, data, "update"); } - public void cancelRequest(RequestId id) { + public void validateRequest(RequestId id, AgentEnrollmentRequestData data) { + changeRequestState(id, data, "validate"); + } + + public void unassignRequest(RequestId id, AgentEnrollmentRequestData data) { + changeRequestState(id, data, "unassign"); + } + + public void assignRequest(RequestId id, AgentEnrollmentRequestData data) { + changeRequestState(id, data, "assign"); + } + + public void changeRequestState(RequestId id, AgentEnrollmentRequestData data, String op) { if (id == null) { - throw new BadRequestException("Bad data input in CertRequestResourceService.cancelRequest!"); + throw new BadRequestException("Bad data input in CertRequestResourceService. op:" + op); + } + + CertRequestDAO dao = new CertRequestDAO(); + try { + dao.changeRequestState(id, servletRequest, data, getLocale(), op); + } catch (ERejectException e) { + CMS.debug("changeRequestState: execution rejected " + e); + throw new CMSException(Response.Status.BAD_REQUEST, + CMS.getUserMessage(getLocale(), "CMS_PROFILE_REJECTED", e.toString())); + } catch (EDeferException e) { + CMS.debug("changeRequestState: execution defered " + e); + // TODO do we throw an exception here? + throw new CMSException(Response.Status.BAD_REQUEST, + CMS.getUserMessage(getLocale(), "CMS_PROFILE_DEFERRED", e.toString())); + } catch (BadRequestDataException e) { + CMS.debug("changeRequestState: bad request data: " + e); + throw new CMSException(Response.Status.BAD_REQUEST, e.toString()); + } catch (EPropertyException e) { + CMS.debug("changeRequestState: execution error " + e); + throw new CMSException(CMS.getUserMessage(getLocale(), + "CMS_PROFILE_PROPERTY_ERROR", e.toString())); + } catch (EProfileException e) { + CMS.debug("ProfileProcessServlet: execution error " + e); + throw new CMSException(CMS.getUserMessage(getLocale(), "CMS_INTERNAL_ERROR")); + } catch (EBaseException e) { + e.printStackTrace(); + throw new CMSException("Problem approving request in CertRequestResource.assignRequest!"); + } catch (RequestNotFoundException e) { + throw new CMSException(Response.Status.BAD_REQUEST, + CMS.getUserMessage(getLocale(), "CMS_REQUEST_NOT_FOUND", id.toString())); } - //TODO implement - throw new CMSException("Problem cancelling request in CertRequestResource.cancelRequest!"); } + + public AgentEnrollmentRequestData reviewRequest(@PathParam("id") RequestId id) { + // auth and authz + AgentEnrollmentRequestData info; + + CertRequestDAO dao = new CertRequestDAO(); + try { + info = dao.reviewRequest(servletRequest, id, uriInfo, getLocale()); + } catch (EBaseException e) { + // log error + e.printStackTrace(); + throw new CMSException("Error getting Cert request info!"); + } + + if (info == null) { + // request does not exist + throw new RequestNotFoundException(id); + } + + return info; + } + } diff --git a/base/common/src/com/netscape/cms/servlet/request/model/AgentEnrollmentRequestData.java b/base/common/src/com/netscape/cms/servlet/request/model/AgentEnrollmentRequestData.java new file mode 100644 index 000000000..fb0874353 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/AgentEnrollmentRequestData.java @@ -0,0 +1,252 @@ +//--- BEGIN COPYRIGHT BLOCK --- +//This program is free software; you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation; version 2 of the License. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License along +//with this program; if not, write to the Free Software Foundation, Inc., +//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//(C) 2012 Red Hat, Inc. +//All rights reserved. +//--- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.request.model; + +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestIdAdapter; +import com.netscape.cms.servlet.profile.model.PolicyDefault; +import com.netscape.cms.servlet.profile.model.ProfileAttribute; +import com.netscape.cms.servlet.profile.model.ProfilePolicy; +import com.netscape.cms.servlet.profile.model.ProfilePolicySet; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class AgentEnrollmentRequestData extends EnrollmentRequestData { + + @XmlElement(name="ProfilePolicySet") + protected List<ProfilePolicySet> policySets = new ArrayList<ProfilePolicySet>(); + + protected String nonce; + + @XmlElement + @XmlJavaTypeAdapter(RequestIdAdapter.class) + protected RequestId requestId; + + protected String requestType; + + protected String requestStatus; + + protected String requestOwner; + + protected String requestCreationTime; + + protected String requestModificationTime; + + protected String requestNotes; + + protected String profileApprovedBy; + + protected String profileSetId; + + protected String profileIsVisible; + + protected String profileName; + + protected String profileDescription; + + protected String profileRemoteHost; + + protected String profileRemoteAddr; + + public String getNonce() { + return nonce; + } + + public void setNonce(String nonce) { + this.nonce = nonce; + } + + public RequestId getRequestId() { + return requestId; + } + + public void setRequestId(RequestId requestId) { + this.requestId = requestId; + } + + public String getRequestType() { + return requestType; + } + + public void setRequestType(String requestType) { + this.requestType = requestType; + } + + public String getRequestStatus() { + return requestStatus; + } + + public void setRequestStatus(String requestStatus) { + this.requestStatus = requestStatus; + } + + public String getRequestOwner() { + return requestOwner; + } + + public void setRequestOwner(String requestOwner) { + this.requestOwner = requestOwner; + } + + public String getRequestCreationTime() { + return requestCreationTime; + } + + public void setRequestCreationTime(String requestCreationTime) { + this.requestCreationTime = requestCreationTime; + } + + public String getRequestModificationTime() { + return requestModificationTime; + } + + public void setRequestModificationTime(String requestModificationTime) { + this.requestModificationTime = requestModificationTime; + } + + public String getRequestNotes() { + return requestNotes; + } + + public void setRequestNotes(String requestNotes) { + this.requestNotes = requestNotes; + } + + public String getProfileApprovedBy() { + return profileApprovedBy; + } + + public void setProfileApprovedBy(String profileApprovedBy) { + this.profileApprovedBy = profileApprovedBy; + } + + public String getProfileSetId() { + return profileSetId; + } + + public void setProfileSetId(String profileSetId) { + this.profileSetId = profileSetId; + } + + public String getProfileIsVisible() { + return profileIsVisible; + } + + public void setProfileIsVisible(String profileIsVisible) { + this.profileIsVisible = profileIsVisible; + } + + public String getProfileName() { + return profileName; + } + + public void setProfileName(String profileName) { + this.profileName = profileName; + } + + public String getProfileDescription() { + return profileDescription; + } + + public void setProfileDescription(String profileDescription) { + this.profileDescription = profileDescription; + } + + public String getProfileRemoteHost() { + return profileRemoteHost; + } + + public void setProfileRemoteHost(String profileRemoteHost) { + this.profileRemoteHost = profileRemoteHost; + } + + public String getProfileRemoteAddr() { + return profileRemoteAddr; + } + + public void setProfileRemoteAddr(String profileRemoteAddr) { + this.profileRemoteAddr = profileRemoteAddr; + } + + public String toString() { + try { + JAXBContext context = JAXBContext.newInstance(AgentEnrollmentRequestData.class); + Marshaller marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + + marshaller.marshal(this, stream); + return stream.toString(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public List<ProfilePolicySet> getPolicySets() { + return policySets; + } + + public void setPolicySets(List<ProfilePolicySet> policySets) { + this.policySets = policySets; + } + + public void addProfilePolicySet(ProfilePolicySet policySet) { + policySets.add(policySet); + } + + public void removeProfilePolicySet(ProfilePolicySet policySet) { + policySets.remove(policySet); + } + + @Override + public HashMap<String,String> toParams() { + HashMap<String,String> ret = super.toParams(); + + if (requestId != null) ret.put("requestId", requestId.toString()); + if (requestNotes != null) ret.put("requestNotes", requestNotes); + if (nonce != null) ret.put("nonces", nonce); + if (requestType != null) ret.put("requestType", requestType); + + for (ProfilePolicySet policySet: policySets) { + for (ProfilePolicy policy: policySet.getPolicies()) { + PolicyDefault def = policy.getDef(); + List<ProfileAttribute> attrs = def.getAttributes(); + for (ProfileAttribute attr: attrs) { + ret.put(attr.getName(), attr.getValue()); + } + } + } + return ret; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/request/model/AgentEnrollmentRequestDataFactory.java b/base/common/src/com/netscape/cms/servlet/request/model/AgentEnrollmentRequestDataFactory.java new file mode 100644 index 000000000..fff1a59df --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/AgentEnrollmentRequestDataFactory.java @@ -0,0 +1,174 @@ +//--- BEGIN COPYRIGHT BLOCK --- +//This program is free software; you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation; version 2 of the License. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License along +//with this program; if not, write to the Free Software Foundation, Inc., +//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//(C) 2012 Red Hat, Inc. +//All rights reserved. +//--- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.request.model; + +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.UriInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.Nonces; +import com.netscape.certsrv.profile.EProfileException; +import com.netscape.certsrv.profile.IPolicyDefault; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileInput; +import com.netscape.certsrv.profile.IProfilePolicy; +import com.netscape.certsrv.property.EPropertyException; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.processors.Processor; +import com.netscape.cms.servlet.profile.model.PolicyConstraint; +import com.netscape.cms.servlet.profile.model.PolicyConstraintFactory; +import com.netscape.cms.servlet.profile.model.PolicyDefault; +import com.netscape.cms.servlet.profile.model.PolicyDefaultFactory; +import com.netscape.cms.servlet.profile.model.ProfileInput; +import com.netscape.cms.servlet.profile.model.ProfileInputFactory; +import com.netscape.cms.servlet.profile.model.ProfilePolicy; +import com.netscape.cms.servlet.profile.model.ProfilePolicySet; + +public class AgentEnrollmentRequestDataFactory { + + public static AgentEnrollmentRequestData create(IRequest request, IProfile profile, UriInfo uriInfo, Locale locale) throws EBaseException { + AgentEnrollmentRequestData ret = new AgentEnrollmentRequestData(); + + if (request.getRequestType().equals("renewal")) { + ret.setIsRenewal(true); + } else { + ret.setIsRenewal(false); + } + + ret.setRequestId(request.getRequestId()); + ret.setRequestType(request.getRequestType()); + ret.setRequestStatus(request.getRequestStatus().toString()); + if (request.getRequestOwner() == null) { + ret.setRequestOwner(""); + } else { + ret.setRequestOwner(request.getRequestOwner()); + } + ret.setRequestCreationTime(request.getCreationTime().toString()); + ret.setRequestModificationTime(request.getModificationTime().toString()); + + ret.setProfileId(profile.getId()); + ret.setProfileApprovedBy(request.getExtDataInString("profileApprovedBy")); + ret.setProfileSetId(request.getExtDataInString("profileSetId")); + if (profile.isVisible()) { + ret.setProfileIsVisible("true"); + } else { + ret.setProfileIsVisible("false"); + } + + ret.setProfileName(profile.getName(locale)); + ret.setProfileDescription(profile.getDescription(locale)); + ret.setProfileRemoteHost(request.getExtDataInString("profileRemoteHost")); + ret.setProfileRemoteAddr(request.getExtDataInString("profileRemoteAddr")); + if (request.getExtDataInString("requestNotes") == null) { + ret.setRequestNotes(""); + } else { + ret.setRequestNotes(request.getExtDataInString("requestNotes")); + } + + // populate profile inputs + Enumeration<String> inputIds = profile.getProfileInputIds(); + while (inputIds.hasMoreElements()) { + IProfileInput input = profile.getProfileInput(inputIds.nextElement()); + ProfileInput addInput = ProfileInputFactory.create(input, request, locale); + ret.addInput(addInput); + } + + String profileSetId = request.getExtDataInString("profileSetId"); + CMS.debug("createAgentCertRequestInfo: profileSetId=" + profileSetId); + Enumeration<String> policyIds = (profileSetId != null && profileSetId.length() > 0) ? + profile.getProfilePolicyIds(profileSetId) : null; + ProfilePolicySet dataPolicySet = new ProfilePolicySet(); + + if (policyIds != null) { + while (policyIds.hasMoreElements()) { + String id = policyIds.nextElement(); + CMS.debug("policyId:" + id); + IProfilePolicy policy = profile.getProfilePolicy(profileSetId, id); + ProfilePolicy dataPolicy = new ProfilePolicy(); + + //populate defaults + IPolicyDefault def = policy.getDefault(); + PolicyDefault dataDef = PolicyDefaultFactory.create(request, locale, def); + dataPolicy.setDef(dataDef); + + //populate constraints + PolicyConstraint dataCons = PolicyConstraintFactory.create(locale, policy.getConstraint()); + dataPolicy.setConstraint(dataCons); + + dataPolicySet.addPolicy(dataPolicy); + } + } + + + ret.addProfilePolicySet(dataPolicySet); + + // TODO populate profile outputs + return ret; + } + + public static AgentEnrollmentRequestData create(CMSRequest cmsReq, IProfile profile, Nonces nonces, Locale locale) + throws EPropertyException, EProfileException { + HttpServletRequest req = cmsReq.getHttpReq(); + IRequest ireq = cmsReq.getIRequest(); + IArgBlock params = cmsReq.getHttpParams(); + + AgentEnrollmentRequestData ret = new AgentEnrollmentRequestData(); + ret.setProfileId(profile.getId()); + ret.setRequestNotes(req.getParameter("requestNotes")); + ret.setRequestId(ireq.getRequestId()); + + if (nonces != null) { + ret.setNonce(req.getParameter(Processor.ARG_REQUEST_NONCE)); + } + + // populate profile policy values + String profileSetId = ireq.getExtDataInString("profileSetId"); + Enumeration<String> policyIds = (profileSetId != null && profileSetId.length() > 0) ? + profile.getProfilePolicyIds(profileSetId) : null; + ProfilePolicySet dataPolicySet = new ProfilePolicySet(); + + if (policyIds != null) { + while (policyIds.hasMoreElements()) { + String id = policyIds.nextElement(); + CMS.debug("policyId:" + id); + IProfilePolicy policy = profile.getProfilePolicy(profileSetId, id); + com.netscape.cms.servlet.profile.model.ProfilePolicy dataPolicy = + new com.netscape.cms.servlet.profile.model.ProfilePolicy(); + + //populate defaults + IPolicyDefault def = policy.getDefault(); + PolicyDefault dataDef = PolicyDefaultFactory.create(params, locale, def); + dataPolicy.setDef(dataDef); + + dataPolicySet.addPolicy(dataPolicy); + CMS.debug(dataPolicy.toString()); + } + } + + ret.addProfilePolicySet(dataPolicySet); + + return ret; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/request/model/CMSRequestInfo.java b/base/common/src/com/netscape/cms/servlet/request/model/CMSRequestInfo.java index b86b39fbd..07a02cd1c 100644 --- a/base/common/src/com/netscape/cms/servlet/request/model/CMSRequestInfo.java +++ b/base/common/src/com/netscape/cms/servlet/request/model/CMSRequestInfo.java @@ -1,3 +1,20 @@ +//--- BEGIN COPYRIGHT BLOCK --- +//This program is free software; you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation; version 2 of the License. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License along +//with this program; if not, write to the Free Software Foundation, Inc., +//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//(C) 2012 Red Hat, Inc. +//All rights reserved. +//--- END COPYRIGHT BLOCK --- package com.netscape.cms.servlet.request.model; import javax.xml.bind.annotation.XmlAccessType; diff --git a/base/common/src/com/netscape/cms/servlet/request/model/CertRequestDAO.java b/base/common/src/com/netscape/cms/servlet/request/model/CertRequestDAO.java index 1d7f8aeae..da1c78661 100644 --- a/base/common/src/com/netscape/cms/servlet/request/model/CertRequestDAO.java +++ b/base/common/src/com/netscape/cms/servlet/request/model/CertRequestDAO.java @@ -17,27 +17,31 @@ // --- END COPYRIGHT BLOCK --- package com.netscape.cms.servlet.request.model; -import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Locale; +import java.util.Random; -import javax.ws.rs.Path; -import javax.ws.rs.core.UriBuilder; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.UriInfo; -import netscape.security.x509.X509CertImpl; - import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.Nonces; import com.netscape.certsrv.ca.ICertificateAuthority; -import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileSubsystem; import com.netscape.certsrv.request.IRequest; import com.netscape.certsrv.request.IRequestQueue; import com.netscape.certsrv.request.RequestId; -import com.netscape.certsrv.request.RequestStatus; -import com.netscape.cms.servlet.cert.CertResource; -import com.netscape.cms.servlet.request.CertRequestResource; +import com.netscape.cms.servlet.cert.EnrollmentProcessor; +import com.netscape.cms.servlet.cert.RenewalProcessor; +import com.netscape.cms.servlet.cert.RequestProcessor; +import com.netscape.cms.servlet.processors.Processor; +import com.netscape.cms.servlet.request.RequestNotFoundException; /** * @author alee @@ -46,16 +50,22 @@ import com.netscape.cms.servlet.request.CertRequestResource; public class CertRequestDAO extends CMSRequestDAO { private IRequestQueue queue; private ICertificateAuthority ca; + IProfileSubsystem ps; + private Nonces nonces = null; + private Random random = null; public static final String ATTR_SERIALNO = "serialNumber"; - private static final String REQ_COMPLETE = "complete"; + public static final String REQ_COMPLETE = "complete"; public CertRequestDAO() { - super("ca"); ca = (ICertificateAuthority) CMS.getSubsystem("ca"); queue = ca.getRequestQueue(); - + if (ca.noncesEnabled()) { + random = new Random(); + nonces = ca.getNonces(); + } + ps = (IProfileSubsystem) CMS.getSubsystem(IProfileSubsystem.ID); } /** @@ -122,86 +132,87 @@ public class CertRequestDAO extends CMSRequestDAO { } /** - * Submits an enrollment request and processes it. + * Gets info for a specific request * - * @param data - * @return info for the request submitted. + * @param id + * @return info for specific request * @throws EBaseException */ - public CertRequestInfo submitRequest(EnrollmentRequestData data, UriInfo uriInfo) throws EBaseException { - - //TODO perform actual profile request. - - throw new EBaseException("Not implemented."); - } - - 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 { + public AgentEnrollmentRequestData reviewRequest(HttpServletRequest servletRequest, RequestId id, + UriInfo uriInfo, Locale locale) throws EBaseException { IRequest request = queue.findRequest(id); - request.setRequestStatus(RequestStatus.CANCELED); - queue.updateRequest(request); - } + if (request == null) { + return null; + } + String profileId = request.getExtDataInString("profileId"); + IProfile profile = ps.getProfile(profileId); - public void cancelRequest(RequestId id) throws EBaseException { - IRequest request = queue.findRequest(id); - request.setRequestStatus(RequestStatus.REJECTED); - queue.updateRequest(request); + AgentEnrollmentRequestData info = AgentEnrollmentRequestDataFactory.create(request, profile, uriInfo, locale); + if (ca.noncesEnabled()) { + addNonce(info, servletRequest); + } + return info; } - private CertRequestInfo createCertRequestInfo(IRequest request, UriInfo uriInfo) { - CertRequestInfo ret = new CertRequestInfo(); - String requestType = request.getRequestType(); - String requestStatus = request.getRequestStatus().toString(); - - ret.setRequestType(requestType); - ret.setRequestStatus(requestStatus); - - ret.setCertRequestType(request.getExtDataInString("cert_request_type")); - - Path certRequestPath = CertRequestResource.class.getAnnotation(Path.class); - RequestId rid = request.getRequestId(); - - UriBuilder reqBuilder = uriInfo.getBaseUriBuilder(); - reqBuilder.path(certRequestPath.value() + "/" + rid); - ret.setRequestURL(reqBuilder.build().toString()); - - //Get Cert info if issued. - - String serialNoStr = null; - - if ((requestType != null) && (requestStatus != null)) { - if (requestStatus.equals(REQ_COMPLETE)) { - X509CertImpl impl[] = new X509CertImpl[1]; - impl[0] = request.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT); - - BigInteger serialNo; - if (impl[0] != null) { - serialNo = impl[0].getSerialNumber(); - serialNoStr = serialNo.toString(); - } + private void addNonce(AgentEnrollmentRequestData info, HttpServletRequest servletRequest) throws EBaseException { + if (nonces != null) { + long n = random.nextLong(); + long m = nonces.addNonce(n, Processor.getSSLClientCertificate(servletRequest)); + if ((n + m) != 0) { + info.setNonce(Long.toString(m)); } + } + } + /** + * Submits an enrollment request and processes it. + * + * @param data + * @return info for the request submitted. + * @throws EBaseException + * @throws ServletException + */ + public CertRequestInfos submitRequest(EnrollmentRequestData data, HttpServletRequest request, UriInfo uriInfo, + Locale locale) throws EBaseException { + HashMap<String, Object> results = null; + if (data.getIsRenewal()) { + RenewalProcessor processor = new RenewalProcessor("caProfileSubmit", locale); + results = processor.processRenewal(data, request); + } else { + EnrollmentProcessor processor = new EnrollmentProcessor("caProfileSubmit", locale); + results = processor.processEnrollment(data, request); } - if (serialNoStr != null && !serialNoStr.equals("")) { - Path certPath = CertResource.class.getAnnotation(Path.class); - UriBuilder certBuilder = uriInfo.getBaseUriBuilder(); - certBuilder.path(certPath.value() + "/" + serialNoStr); - ret.setCertURL(certBuilder.build().toString()); + CertRequestInfos ret = new CertRequestInfos(); + ArrayList<CertRequestInfo> infos = new ArrayList<CertRequestInfo>(); + IRequest reqs[] = (IRequest[]) results.get(Processor.ARG_REQUESTS); + for (IRequest req : reqs) { + CertRequestInfo info = CertRequestInfoFactory.create(req, uriInfo); + infos.add(info); } + // TODO - what happens if the errorCode is internal error ? + ret.setRequests(infos); + ret.setLinks(null); return ret; } + public void changeRequestState(RequestId id, HttpServletRequest request, AgentEnrollmentRequestData data, + Locale locale, String op) throws EBaseException { + IRequest ireq = queue.findRequest(id); + if (ireq == null) { + throw new RequestNotFoundException(id); + } + + RequestProcessor processor = new RequestProcessor("caProfileProcess", locale); + processor.processRequest(request, data, ireq, op); + } + + @Override public CertRequestInfo createCMSRequestInfo(IRequest request, UriInfo uriInfo) { - return createCertRequestInfo(request, uriInfo); + return CertRequestInfoFactory.create(request, uriInfo); } } diff --git a/base/common/src/com/netscape/cms/servlet/request/model/CertRequestInfo.java b/base/common/src/com/netscape/cms/servlet/request/model/CertRequestInfo.java index 25083126d..20c298136 100644 --- a/base/common/src/com/netscape/cms/servlet/request/model/CertRequestInfo.java +++ b/base/common/src/com/netscape/cms/servlet/request/model/CertRequestInfo.java @@ -74,6 +74,7 @@ public class CertRequestInfo extends CMSRequestInfo { */ public CertId getCertId() { + if (certURL == null) return null; String id = certURL.substring(certURL.lastIndexOf("/") + 1); return new CertId(id); } diff --git a/base/common/src/com/netscape/cms/servlet/request/model/CertRequestInfoFactory.java b/base/common/src/com/netscape/cms/servlet/request/model/CertRequestInfoFactory.java new file mode 100644 index 000000000..7045f3366 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/CertRequestInfoFactory.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) 2012 Red Hat, Inc. +//All rights reserved. +//--- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.request.model; + +import java.math.BigInteger; + +import javax.ws.rs.Path; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; + +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.cert.CertResource; +import com.netscape.cms.servlet.request.CertRequestResource; + +public class CertRequestInfoFactory { + + public static final String REQ_COMPLETE = "complete"; + + public static CertRequestInfo create(IRequest request, UriInfo uriInfo) { + CertRequestInfo ret = new CertRequestInfo(); + String requestType = request.getRequestType(); + String requestStatus = request.getRequestStatus().toString(); + + ret.setRequestType(requestType); + ret.setRequestStatus(requestStatus); + + ret.setCertRequestType(request.getExtDataInString("cert_request_type")); + + Path certRequestPath = CertRequestResource.class.getAnnotation(Path.class); + RequestId rid = request.getRequestId(); + + UriBuilder reqBuilder = uriInfo.getBaseUriBuilder(); + reqBuilder.path(certRequestPath.value() + "/" + rid); + ret.setRequestURL(reqBuilder.build().toString()); + + //Get cert info if issued. + String serialNoStr = null; + + if ((requestType != null) && (requestStatus != null)) { + if (requestStatus.equals(REQ_COMPLETE)) { + X509CertImpl impl[] = new X509CertImpl[1]; + impl[0] = request.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT); + + BigInteger serialNo; + if (impl[0] != null) { + serialNo = impl[0].getSerialNumber(); + serialNoStr = serialNo.toString(); + } + } + + } + + if (serialNoStr != null && !serialNoStr.equals("")) { + Path certPath = CertResource.class.getAnnotation(Path.class); + UriBuilder certBuilder = uriInfo.getBaseUriBuilder(); + certBuilder.path(certPath.value() + "/" + serialNoStr); + ret.setCertURL(certBuilder.build().toString()); + } + return ret; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/request/model/EnrollmentRequestData.java b/base/common/src/com/netscape/cms/servlet/request/model/EnrollmentRequestData.java index f2979ebce..caff0261d 100644 --- a/base/common/src/com/netscape/cms/servlet/request/model/EnrollmentRequestData.java +++ b/base/common/src/com/netscape/cms/servlet/request/model/EnrollmentRequestData.java @@ -24,8 +24,10 @@ package com.netscape.cms.servlet.request.model; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import javax.ws.rs.core.MultivaluedMap; import javax.xml.bind.JAXBContext; @@ -38,6 +40,7 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import com.netscape.cms.servlet.profile.model.ProfileInput; +import com.netscape.cms.servlet.profile.model.ProfileOutput; /** * @author jmagne @@ -50,6 +53,7 @@ public class EnrollmentRequestData { private static final String PROFILE_ID = "profileId"; private static final String RENEWAL = "renewal"; + private static final String SERIAL_NUM = "serial_num"; @XmlElement protected String profileId; @@ -57,18 +61,30 @@ public class EnrollmentRequestData { @XmlElement protected boolean isRenewal; + @XmlElement + protected String serialNum; // used for one type of renewal + + @XmlElement + protected String remoteHost; + + @XmlElement + protected String remoteAddr; + @XmlElement(name = "Input") protected List<ProfileInput> inputs = new ArrayList<ProfileInput>(); + @XmlElement(name = "Output") + protected List<ProfileOutput> outputs = new ArrayList<ProfileOutput>(); + public EnrollmentRequestData() { + // required for jaxb } public EnrollmentRequestData(MultivaluedMap<String, String> form) { profileId = form.getFirst(PROFILE_ID); String renewalStr = form.getFirst(RENEWAL); - + serialNum = form.getFirst(SERIAL_NUM); isRenewal = new Boolean(renewalStr); - } /** @@ -94,7 +110,22 @@ public class EnrollmentRequestData { return isRenewal; } - public ProfileInput addInput(String name) { + public void addInput(ProfileInput input) { + ProfileInput curInput = getInput(input.getInputId()); + if (curInput != null) { + getInputs().remove(curInput); + } + getInputs().add(input); + } + + public void deleteInput(ProfileInput input) { + ProfileInput curInput = getInput(input.getInputId()); + if (curInput != null) { + getInputs().remove(curInput); + } + } + + public ProfileInput createInput(String name) { ProfileInput oldInput = getInput(name); @@ -104,7 +135,7 @@ public class EnrollmentRequestData { ProfileInput newInput = new ProfileInput(); newInput.setInputId(name); - inputs.add(newInput); + getInputs().add(newInput); return newInput; } @@ -113,14 +144,11 @@ public class EnrollmentRequestData { ProfileInput input = null; - Iterator<ProfileInput> it = inputs.iterator(); + Iterator<ProfileInput> it = getInputs().iterator(); ProfileInput curInput = null; - while (it.hasNext()) - - { + while (it.hasNext()) { curInput = it.next(); - if (curInput != null && curInput.getInputId().equals(name)) break; } @@ -128,6 +156,35 @@ public class EnrollmentRequestData { return input; } + public void addOutput(ProfileOutput output) { + ProfileOutput curOutput = getOutput(output.getOutputId()); + if (curOutput != null) { + getOutputs().remove(curOutput); + } + getOutputs().add(output); + } + + public void deleteOutput(ProfileOutput output) { + ProfileOutput curOutput = getOutput(output.getOutputId()); + if (curOutput != null) { + getInputs().remove(curOutput); + } + } + + public ProfileOutput getOutput(String name) { + ProfileOutput output = null; + ProfileOutput curOutput = null; + + Iterator<ProfileOutput> it = getOutputs().iterator(); + while (it.hasNext()) { + curOutput = it.next(); + if (curOutput != null && curOutput.getOutputId().equals(name)) + break; + } + + return output; + } + /** * @param renewal the renewal to set */ @@ -135,6 +192,24 @@ public class EnrollmentRequestData { this.isRenewal = isRenewal; } + public HashMap<String, String> toParams() { + HashMap<String, String> ret = new HashMap<String, String>(); + ret.put("isRenewal", Boolean.valueOf(isRenewal).toString()); + if (profileId != null) ret.put(PROFILE_ID, profileId); + if (serialNum != null) ret.put(SERIAL_NUM, serialNum); + if (remoteHost != null) ret.put("remoteHost", remoteHost); + if (remoteAddr != null) ret.put("remoteAddr", remoteAddr); + + for (ProfileInput input: inputs) { + Map<String, String> attrs = input.getAttributes(); + for (Map.Entry<String, String> entry: attrs.entrySet()) { + ret.put(entry.getKey(), entry.getValue()); + } + } + + return ret; + } + public static void main(String args[]) throws Exception { EnrollmentRequestData data = new EnrollmentRequestData(); data.setProfileId("caUserCert"); @@ -142,13 +217,13 @@ public class EnrollmentRequestData { //Simulate a "caUserCert" Profile enrollment - ProfileInput certReq = data.addInput("KeyGenInput"); + ProfileInput certReq = data.createInput("KeyGenInput"); certReq.setInputAttr("cert_request_type", "crmf"); certReq.setInputAttr( "cert_request", "MIIBozCCAZ8wggEFAgQBMQp8MIHHgAECpQ4wDDEKMAgGA1UEAxMBeKaBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2NgaPHp0jiohcP4M+ufrJOZEqH8GV+liu5JLbT8nWpkfhC+8EUBqT6g+n3qroSxIcNVGNdcsBEqs1utvpItzyslAbpdyat3WwQep1dWMzo6RHrPDuIoxNA0Yka1n3qEX4U//08cLQtUv2bYglYgN/hOCNQemLV6vZWAv0n7zelkCAwEAAakQMA4GA1UdDwEB/wQEAwIF4DAzMBUGCSsGAQUFBwUBAQwIcmVnVG9rZW4wGgYJKwYBBQUHBQECDA1hdXRoZW50aWNhdG9yoYGTMA0GCSqGSIb3DQEBBQUAA4GBAJ1VOQcaSEhdHa94s8kifVbSZ2WZeYE5//qxL6wVlEst20vq4ybj13CetnbN3+WT49Zkwp7Fg+6lALKgSk47suTg3EbbQDm+8yOrC0nc/q4PTRoHl0alMmUxIhirYc1t3xoCMqJewmjX1bNP8lpVIZAYFZo4eZCpZaiSkM5BeHhz"); - ProfileInput subjectName = data.addInput("SubjectNameInput"); + ProfileInput subjectName = data.createInput("SubjectNameInput"); subjectName.setInputAttr("sn_uid", "jmagne"); subjectName.setInputAttr("sn_e", "jmagne@redhat.com"); subjectName.setInputAttr("sn_c", "US"); @@ -159,7 +234,7 @@ public class EnrollmentRequestData { subjectName.setInputAttr("sn_cn", "Common"); subjectName.setInputAttr("sn_o", "RedHat"); - ProfileInput submitter = data.addInput("SubmitterInfoInput"); + ProfileInput submitter = data.createInput("SubmitterInfoInput"); submitter.setInputAttr("requestor_name", "admin"); submitter.setInputAttr("requestor_email", "admin@redhat.com"); submitter.setInputAttr("requestor_phone", "650-555-5555"); @@ -199,4 +274,48 @@ public class EnrollmentRequestData { } } + public String getSerialNum() { + return serialNum; + } + + public void setSerialNum(String serialNum) { + this.serialNum = serialNum; + } + + public List<ProfileInput> getInputs() { + return inputs; + } + + public void setInputs(List<ProfileInput> inputs) { + this.inputs = inputs; + } + + public String getRemoteAddr() { + return remoteAddr; + } + + public void setRemoteAddr(String remoteAddr) { + this.remoteAddr = remoteAddr; + } + + public String getRemoteHost() { + return remoteHost; + } + + public void setRemoteHost(String remoteHost) { + this.remoteHost = remoteHost; + } + + public List<ProfileOutput> getOutputs() { + return outputs; + } + + public void setOutputs(List<ProfileOutput> outputs) { + this.outputs = outputs; + } + + public void setRenewal(boolean isRenewal) { + this.isRenewal = isRenewal; + } + } diff --git a/base/common/src/com/netscape/cms/servlet/request/model/EnrollmentRequestDataFactory.java b/base/common/src/com/netscape/cms/servlet/request/model/EnrollmentRequestDataFactory.java new file mode 100644 index 000000000..3a09b7608 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/EnrollmentRequestDataFactory.java @@ -0,0 +1,51 @@ +//--- BEGIN COPYRIGHT BLOCK --- +//This program is free software; you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation; version 2 of the License. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License along +//with this program; if not, write to the Free Software Foundation, Inc., +//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//(C) 2012 Red Hat, Inc. +//All rights reserved. +//--- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.request.model; + +import java.util.Enumeration; +import java.util.Locale; + +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.profile.EProfileException; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileInput; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.profile.model.ProfileInput; +import com.netscape.cms.servlet.profile.model.ProfileInputFactory; + +public class EnrollmentRequestDataFactory { + + public static EnrollmentRequestData create(CMSRequest cmsReq, IProfile profile, Locale locale) + throws EProfileException { + IArgBlock params = cmsReq.getHttpParams(); + + EnrollmentRequestData ret = new EnrollmentRequestData(); + ret.setProfileId(profile.getId()); + + // populate profile inputs + Enumeration<String> inputIds = profile.getProfileInputIds(); + while (inputIds.hasMoreElements()) { + IProfileInput input = profile.getProfileInput(inputIds.nextElement()); + ProfileInput addInput = ProfileInputFactory.create(input, params, locale); + ret.addInput(addInput); + } + + return ret; + } + +} |