diff options
author | Ade Lee <alee@redhat.com> | 2012-05-13 23:04:36 -0400 |
---|---|---|
committer | Ade Lee <alee@redhat.com> | 2012-07-03 13:58:45 -0400 |
commit | 9ce810c0b2fef9f70178dbeee8a3523755a2a260 (patch) | |
tree | a25cd9e9969898506ed2a4cb17a3cfbeb68496cf | |
parent | 0f3451befbc14bd6ec29d9e1e3845f970f288653 (diff) | |
download | pki-9ce810c0b2fef9f70178dbeee8a3523755a2a260.tar.gz pki-9ce810c0b2fef9f70178dbeee8a3523755a2a260.tar.xz pki-9ce810c0b2fef9f70178dbeee8a3523755a2a260.zip |
Adding restful interface to create certificate requests and issue certificates.
Refactored ProfileSubmitServlet to make the flow clearer. Both the legacy servlets
and the new RESTful servlets use common ProfileProcessor objects that contain the main
business logic, so that the amount of duplicated code is minimized.
Refactored ProfileProcessServlet to use the new common classes.
Addressed review comments. Removed an unneeded class and reverted some unneeded jaxb
annotations. Added factory methods.
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; + } + +} |