>From d42fe72a5599cd0457fee5e3c8bbe3b894c3bdfc Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Sun, 13 May 2012 23:04:36 -0400
Subject: [PATCH] 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.
---
 .../netscape/cms/servlet/test/CARestClient.java    |   35 +-
 .../src/com/netscape/cms/servlet/test/CATest.java  |  166 ++-
 base/ca/shared/conf/CS.cfg.in                      |    9 +
 base/common/src/CMakeLists.txt                     |   21 +
 .../certsrv/base/BadRequestDataException.java      |   24 +
 .../com/netscape/certsrv/property/Descriptor.java  |   17 +
 .../com/netscape/certsrv/request/RequestId.java    |    4 +
 .../cms/servlet/base/CMSResourceService.java       |    4 +
 .../com/netscape/cms/servlet/base/CMSServlet.java  |    4 +
 .../netscape/cms/servlet/cert/CertProcessor.java   |  351 +++++
 .../cms/servlet/cert/EnrollmentProcessor.java      |  205 +++
 .../cms/servlet/cert/RenewalProcessor.java         |  345 +++++
 .../cms/servlet/cert/RequestProcessor.java         |  475 ++++++
 .../cms/servlet/common/AuthCredentials.java        |    6 +-
 .../netscape/cms/servlet/common/ServletUtils.java  |   42 +
 .../netscape/cms/servlet/processors/Processor.java | 1259 ++++++++++++++++
 .../cms/servlet/profile/ProfileProcessServlet.java |  915 +-----------
 .../cms/servlet/profile/ProfileServlet.java        |   69 +
 .../cms/servlet/profile/ProfileSubmitServlet.java  | 1513 ++------------------
 .../servlet/profile/model/PolicyConstraint.java    |   73 +
 .../profile/model/PolicyConstraintFactory.java     |   42 +
 .../profile/model/PolicyConstraintValue.java       |   61 +
 .../cms/servlet/profile/model/PolicyDefault.java   |   73 +
 .../profile/model/PolicyDefaultFactory.java        |   65 +
 .../servlet/profile/model/ProfileAttribute.java    |   80 ++
 .../cms/servlet/profile/model/ProfileData.java     |    1 +
 .../cms/servlet/profile/model/ProfileDataInfo.java |   10 +-
 .../cms/servlet/profile/model/ProfileInput.java    |    5 +
 .../servlet/profile/model/ProfileInputFactory.java |   40 +
 .../model/ProfileOutput.java}                      |   75 +-
 .../profile/model/ProfileOutputFactory.java        |   47 +
 .../cms/servlet/profile/model/ProfilePolicy.java   |   82 ++
 ...{ProfileDataInfo.java => ProfilePolicySet.java} |   56 +-
 .../cms/servlet/request/CertRequestResource.java   |   45 +-
 .../request/CertRequestResourceService.java        |  126 +-
 .../request/model/AgentEnrollmentRequestData.java  |  252 ++++
 .../model/AgentEnrollmentRequestDataFactory.java   |  174 +++
 .../cms/servlet/request/model/CMSRequestInfo.java  |   17 +
 .../cms/servlet/request/model/CertRequestDAO.java  |  165 ++-
 .../cms/servlet/request/model/CertRequestInfo.java |    1 +
 .../request/model/CertRequestInfoFactory.java      |   81 ++
 .../request/model/EnrollmentRequestData.java       |  143 +-
 .../model/EnrollmentRequestDataFactory.java        |   51 +
 43 files changed, 4737 insertions(+), 2492 deletions(-)
 create mode 100644 base/common/src/com/netscape/certsrv/base/BadRequestDataException.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/cert/CertProcessor.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/cert/RenewalProcessor.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/cert/RequestProcessor.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/processors/Processor.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/profile/model/PolicyConstraint.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/profile/model/PolicyConstraintFactory.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/profile/model/PolicyConstraintValue.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/profile/model/PolicyDefault.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/profile/model/PolicyDefaultFactory.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/profile/model/ProfileAttribute.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/profile/model/ProfileInputFactory.java
 copy base/common/src/com/netscape/cms/servlet/{request/model/CertRequestInfo.java => profile/model/ProfileOutput.java} (50%)
 create mode 100644 base/common/src/com/netscape/cms/servlet/profile/model/ProfileOutputFactory.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/profile/model/ProfilePolicy.java
 copy base/common/src/com/netscape/cms/servlet/profile/model/{ProfileDataInfo.java => ProfilePolicySet.java} (58%)
 create mode 100644 base/common/src/com/netscape/cms/servlet/request/model/AgentEnrollmentRequestData.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/request/model/AgentEnrollmentRequestDataFactory.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/request/model/CertRequestInfoFactory.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/request/model/EnrollmentRequestDataFactory.java

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 775c3d9b69b2bdbbf53c35ed9785705dfcad39a6..67138e52984536fd0ce34dcc45f8027432fe11fc 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 c3d55527ca030dc14049a5f1bed683690d20cd58..9afb1f38652947cc348730106745c0286c122efc 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
+        // submit a RA authenticated user cert request
+        EnrollmentRequestData rdata = createRAUserCertEnrollment();
+        enrollCertRequest(client, rdata);
 
-        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");
+        // now try a manually approved server cert
+        EnrollmentRequestData serverData = createServerCertEnrollment();
+        enrollAndApproveCertRequest(client,serverData);
 
-        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());
-        }
-
-        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 ada97c4fadbe255f15d87ce6319a901d1737b25b..527de831d0978f87950a99bee0e16dd3a51953b6 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 7b73a8536c1c282e3491122f148cea456cbc4603..6d8386faf2f1aedd0bb4fecead3a4aa124be8307 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 0000000000000000000000000000000000000000..268221eae726ed93b37d08e3ae721ace3340a43d
--- /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 4b2baf5611edf9a9d0566626d59f4223e9132f61..d3048e0b9b8be0371044d9c208dce3f06cb8767d 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 795fdaa2abadb871a832b6978c41e911f8405aee..8cd8c5711dde2219fec95cf517e2e5658f7980fc 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 85ccbf9f7100e2e8768129b470721491ddf53713..d6b4a9e42605a394bcf42bdecc59e54c12f0b3c6 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 1c610996f4dd251b0ef557e6ab0de69a7b8e7c35..f035285e2f31063ebfa417e955154d9d42ec689b 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 0000000000000000000000000000000000000000..13b0072b4e1be0d98a1c6332bf712616dc24836d
--- /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 0000000000000000000000000000000000000000..8b48f0d73847bcef6a03e46cdafbf590ca7e005f
--- /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 0000000000000000000000000000000000000000..cc4dd12ae04f61c88f59994fcb2fbafe01b11b1e
--- /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 0000000000000000000000000000000000000000..9bb0c4b6483b6a5b71c588744bcba471df48c63b
--- /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 f01d75c98d6b1b44a1d9beaad5b82aed47f8b292..32ae0fcc815bb2afc304726266bccc4c9fef6a6a 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 856679e3aad791cdbc552d525670af26f572882a..a709b6b0282e51c1fd45c24badbc673403cd8339 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 0000000000000000000000000000000000000000..d5893a4799be422ea7339163ce7f0a9d380ba1c8
--- /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 996b65d78ffbfee7a877133477b7f62b1a44d9af..0f9f341446d53b9d67839defae1f0ac1b20a6561 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";
 
     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;
-            }
-        }
+        RequestProcessor processor = new RequestProcessor("caProfileProcess", locale);
 
-        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();
-
-        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");
-            }
+            setError(args, CMS.getUserMessage(locale, "CMS_PROFILE_ID_NOT_FOUND"), request, response);
             return;
         }
+        CMS.debug("ProfileProcessServlet: profileId=" + profileId);
 
-        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");
-            }
-            return;
-        }
-
-        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++;
-        }
-
-    }
-
-    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);
+        outputTemplate(request, response, args);
     }
 
-    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 e975161da166ee2ace50d7adfd4330f811a6e7a5..be331d6ef8922f8d17104c61b6052b499f3576bf 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 85ef4fa0fe93f078ec84c9073a31900ad8c1d27a..7b0813d715fa97c7db69f1e020a189c7d05ed6a3 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");
-                    }
-                }
-            }
-        }
 
-    }
+    public void process(CMSRequest cmsReq) throws EBaseException {
+        HttpServletRequest request = cmsReq.getHttpReq();
+        HttpServletResponse response = cmsReq.getHttpResp();
+        boolean xmlOutput = getXMLOutput(request);
 
-    private void setCredentialsIntoContext(HttpServletRequest request, IProfileAuthenticator authenticator,
-            IProfileContext ctx) {
-        Enumeration<String> authIds = authenticator.getValueNames();
+        Locale locale = getLocale(request);
 
-        if (authIds != null) {
-            CMS.debug("ProfileSubmitServlet:setCredentialsIntoContext() authNames not null");
-            while (authIds.hasMoreElements()) {
-                String authName = authIds.nextElement();
+        HashMap<String, Object> results = null;
+        String renewal = request.getParameter("renewal");
 
-                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");
-        }
-    }
-
-    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("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");
+        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();
                 }
-            } 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");
-                }
-            }
 
-            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();
+                ArgList requestlist = new ArgList();
 
-        if (authNames != null) {
-            while (authNames.hasMoreElements()) {
-                String authName = authNames.nextElement();
-
-                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);
             }
-        }
-    }
+            args.set(ARG_REQUEST_LIST, requestlist);
+            args.set(ARG_ERROR_CODE, "0");
+            args.set(ARG_ERROR_REASON, "");
 
-    /*
-     * 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("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 0000000000000000000000000000000000000000..588431a83e1b25116210d3faa6382b35046e7d9e
--- /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 0000000000000000000000000000000000000000..bd361a75226821b8d5a136df78a0772d0eda6878
--- /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 0000000000000000000000000000000000000000..7b60e7ea6228a262bebbd1b0cbcc08797b4e4dcf
--- /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 0000000000000000000000000000000000000000..2c66fc9dcbf70efd1a3fd88c5093443ecf642d99
--- /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 0000000000000000000000000000000000000000..6b9379f0bec126ed51a6ef648c83753708122f5f
--- /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 0000000000000000000000000000000000000000..616c0695d423113dfd3a4683f7cd14ab9d61ed3a
--- /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 22a59c4701703265e533e822475f476c0b71e795..7f7f26b2929776ac8f435f56ec775e1ff497b3a7 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 63f005b5447ecb8c080ce7e8ea62a05af178e69e..d5083c7a4c690ef905c530d70fe0642b7b33351d 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 a0aea9fd456130959e1db4f065d0776dd4b1985a..631a013ccabb00c3e837612c50d4e43e3ac6022b 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 0000000000000000000000000000000000000000..67d3e9a2c4613c82ec4a37ba84d74016097ef4dc
--- /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/request/model/CertRequestInfo.java b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileOutput.java
similarity index 50%
copy from base/common/src/com/netscape/cms/servlet/request/model/CertRequestInfo.java
copy to base/common/src/com/netscape/cms/servlet/profile/model/ProfileOutput.java
index 25083126d58cd876132bc479308597dd9ae444c1..f27db4101d92794aedef6f1ecd3dcd6c0ba33d99 100644
--- a/base/common/src/com/netscape/cms/servlet/request/model/CertRequestInfo.java
+++ b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileOutput.java
@@ -12,70 +12,73 @@
 // with this program; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 //
-// (C) 2011 Red Hat, Inc.
+// (C) 2007 Red Hat, Inc.
 // All rights reserved.
 // --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.profile.model;
 
-package com.netscape.cms.servlet.request.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;
 
-import com.netscape.certsrv.dbs.certdb.CertId;
-
-@XmlRootElement(name = "CertRequestInfo")
+@XmlRootElement
 @XmlAccessorType(XmlAccessType.FIELD)
-public class CertRequestInfo extends CMSRequestInfo {
+public class ProfileOutput {
+
+    public ProfileOutput() {
+        // required for jaxb
+    }
+
+    @XmlElement
+    private String outputId;
+
+    @XmlElement(name = "attributes")
+    private List<ProfileAttribute> attrs = new ArrayList<ProfileAttribute>();
 
     @XmlElement
-    protected String certURL;
+    private String name;
 
     @XmlElement
-    protected String certRequestType;
+    private String text;
 
-    public CertRequestInfo() {
-        // required to be here for JAXB (defaults)
+    public String getOutputId() {
+        return outputId;
     }
 
-    /**
-     * @param certRequestType to set
-     */
+    public void setOutputId(String OutputId) {
+        this.outputId = OutputId;
+    }
 
-    public void setCertRequestType(String certRequestType) {
-        this.certRequestType = certRequestType;
+    public List<ProfileAttribute> getAttrs() {
+        return attrs;
     }
 
-    /**
-     * @return the certRequestType
-     */
+    public void setAttrs(List<ProfileAttribute> attrs) {
+        this.attrs = attrs;
+    }
 
-    public String getCertRequestType() {
-        return certRequestType;
+    public String getName() {
+        return name;
     }
 
-    /**
-     * @set the certURL
-     */
-    public void setCertURL(String certURL) {
-        this.certURL = certURL;
+    public void setName(String name) {
+        this.name = name;
     }
 
-    /**
-     * @return the certURL
-     */
-    public String getCertURL() {
-        return certURL;
+    public String getText() {
+        return text;
     }
 
-    /**
-     * @return the certId
-     */
+    public void setText(String text) {
+        this.text = text;
+    }
 
-    public CertId getCertId() {
-        String id = certURL.substring(certURL.lastIndexOf("/") + 1);
-        return new CertId(id);
+    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 0000000000000000000000000000000000000000..93bbaa2c577fdbe1d4dfd9361c057ca6169bf5e3
--- /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 0000000000000000000000000000000000000000..a24f936195e13bafc282262e59a2973d9549a6cf
--- /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/ProfileDataInfo.java b/base/common/src/com/netscape/cms/servlet/profile/model/ProfilePolicySet.java
similarity index 58%
copy from base/common/src/com/netscape/cms/servlet/profile/model/ProfileDataInfo.java
copy to base/common/src/com/netscape/cms/servlet/profile/model/ProfilePolicySet.java
index 63f005b5447ecb8c080ce7e8ea62a05af178e69e..784f5670d87760fbfc318824d21020d3f2dcc127 100644
--- a/base/common/src/com/netscape/cms/servlet/profile/model/ProfileDataInfo.java
+++ b/base/common/src/com/netscape/cms/servlet/profile/model/ProfilePolicySet.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
@@ -14,59 +12,39 @@ package com.netscape.cms.servlet.profile.model;
 //with this program; if not, write to the Free Software Foundation, Inc.,
 //51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 //
-//(C) 2011 Red Hat, Inc.
+//(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;
-import javax.xml.bind.annotation.XmlAccessorType;
 
-/**
- * @author alee
- * 
- */
-@XmlRootElement(name = "ProfileDataInfo")
+@XmlRootElement
 @XmlAccessorType(XmlAccessType.FIELD)
-public class ProfileDataInfo {
-
-    @XmlElement
-    protected String profileURL;
-
+public class ProfilePolicySet {
     @XmlElement
-    protected String profileId;
-
-    public ProfileDataInfo() {
-        // required for JAXB (defaults)
-    }
+    protected List<ProfilePolicy> policies = new ArrayList<ProfilePolicy>();
 
-    /**
-     * @return the profileURL
-     */
-    public String getProfileURL() {
-        return profileURL;
+    public List<ProfilePolicy> getPolicies() {
+        return policies;
     }
 
-    /**
-     * @param keyURL the profileURL to set
-     */
-    public void setProfileURL(String profileURL) {
-        this.profileURL = profileURL;
+    public void setPolicies(List<ProfilePolicy> policies) {
+        this.policies = policies;
     }
 
-    public void setProfileId(String profileId) {
-        this.profileId = profileId;
+    public void addPolicy(ProfilePolicy policy) {
+        policies.add(policy);
     }
 
-    /**
-     * @return the profile ID in the profileURL
-     */
-    public String getProfileId() {
-        return profileId;
+    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 5dc97650dd478471eaa3e3cfb285de2d9ec3364d..7bb23dbd5f687c1f25e3184a6659c87b93d65ad6 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 40f57a7a70dad3252d6a46eec012c3441d2ffd03..b31d9961d0b485f4ec525e074405035b4f481659 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");
+    }
+
+    public void cancelRequest(RequestId id, AgentEnrollmentRequestData data) {
+        changeRequestState(id, data, "cancel");
+    }
+
+    public void updateRequest(RequestId id, AgentEnrollmentRequestData data) {
+        changeRequestState(id, data, "update");
+    }
 
-        throw new CMSException("Problem rejecting request in CertRequestResource.rejectRequest!");
+    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 cancelRequest(RequestId id) {
+    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);
         }
-        //TODO implement
-        throw new CMSException("Problem cancelling request in CertRequestResource.cancelRequest!");
+
+        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()));
+        }
+    }
+
+    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 0000000000000000000000000000000000000000..fb08743533db21109e31293d0f9bce8ab21b1de3
--- /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 0000000000000000000000000000000000000000..fff1a59dfb42fb7aa62c5faa12f7dc1bde06bd8e
--- /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 b86b39fbdc3970db4e16fae9aedabb22a61c0a8f..07a02cd1c640e9c54e6308a192a76473c7041011 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 1d7f8aeae2630b234625d7d08987d07792c89a5e..da1c786611df95aecf0af498abbaf44c43f62498 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 {
     }
 
     /**
+     * Gets info for a specific request
+     *
+     * @param id
+     * @return info for specific request
+     * @throws EBaseException
+     */
+    public AgentEnrollmentRequestData reviewRequest(HttpServletRequest servletRequest, RequestId id,
+            UriInfo uriInfo, Locale locale) throws EBaseException {
+        IRequest request = queue.findRequest(id);
+        if (request == null) {
+            return null;
+        }
+        String profileId = request.getExtDataInString("profileId");
+        IProfile profile = ps.getProfile(profileId);
+
+        AgentEnrollmentRequestData info = AgentEnrollmentRequestDataFactory.create(request, profile, uriInfo, locale);
+        if (ca.noncesEnabled()) {
+            addNonce(info, servletRequest);
+        }
+        return info;
+    }
+
+
+    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 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 {
-        IRequest request = queue.findRequest(id);
-        request.setRequestStatus(RequestStatus.CANCELED);
-        queue.updateRequest(request);
-    }
-
-    public void cancelRequest(RequestId id) throws EBaseException {
-        IRequest request = queue.findRequest(id);
-        request.setRequestStatus(RequestStatus.REJECTED);
-        queue.updateRequest(request);
-    }
-
-    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();
-                }
-            }
-
+    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 25083126d58cd876132bc479308597dd9ae444c1..20c298136b37749c85fe9ed224d262328d641ff0 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 0000000000000000000000000000000000000000..7045f3366e6fef0b7807d9df1957a5e817dc6844
--- /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 f2979ebced50bdbca53564cc075d15e5894f0d11..caff0261d253347ab863e8adddb7db2debb61c26 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 0000000000000000000000000000000000000000..3a09b7608cb3c0b07c5f79c8628acd0fa549a201
--- /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;
+    }
+
+}
-- 
1.7.10.1

