From 5ea434ff081455e6d2be77f316bacda292658a49 Mon Sep 17 00:00:00 2001 From: Ade Lee Date: Wed, 23 May 2012 16:03:04 -0400 Subject: Second checkin - this adds ProfileProcessor and some logic to do cert enrollment through rest --- .../cms/servlet/profile/ProfileProcessor.java | 1602 ++++++++++++++++++++ .../cms/servlet/profile/model/ProfileData.java | 1 + .../cms/servlet/profile/model/ProfileInput.java | 1 + .../cms/servlet/request/model/CertRequestDAO.java | 32 +- .../request/model/EnrollmentRequestData.java | 13 + .../request/model/ExtendableHttpRequest.java | 29 + 6 files changed, 1675 insertions(+), 3 deletions(-) create mode 100644 base/common/src/com/netscape/cms/servlet/profile/ProfileProcessor.java create mode 100644 base/common/src/com/netscape/cms/servlet/request/model/ExtendableHttpRequest.java diff --git a/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessor.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessor.java new file mode 100644 index 00000000..b92b31e9 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessor.java @@ -0,0 +1,1602 @@ +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.LinkedHashSet; +import java.util.Locale; +import java.util.StringTokenizer; + +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.authority.IAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.IAuthzSubsystem; +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.IProfileSubsystem; +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.ArgSet; +import com.netscape.certsrv.util.IStatsSubsystem; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.AuthCredentials; +import com.netscape.cmsutil.util.Utils; + +public class ProfileProcessor { + + /** + * + */ + private static final String ARG_AUTH_TOKEN = "auth_token"; + private static final String ARG_REQUEST_OWNER = "requestOwner"; + private 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"; + + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + + private String profileID = null; + private String mProfileSubId = null; + private String authorityId = null; + private String aclMethod = null; + private Locale locale = null; + + private IAuthority authority = null; + private IAuthzSubsystem authz = null; + + //logging and stats + protected ILogger signedAuditLogger = CMS.getSignedAuditLogger(); + protected LinkedHashSet statEvents = null; + + 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"; + private final static String LOGGING_SIGNED_AUDIT_AUTHZ_FAIL = + "LOGGING_SIGNED_AUDIT_AUTHZ_FAIL_4"; + private final static String LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS = + "LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS_4"; + private final static String LOGGING_SIGNED_AUDIT_ROLE_ASSUME = + "LOGGING_SIGNED_AUDIT_ROLE_ASSUME_3"; + + public ProfileProcessor(String authorityId, String profileID, String aclMethod, Locale locale) { + this.authorityId = authorityId; + this.profileID = profileID; + this.aclMethod = aclMethod; + this.locale = locale; + + if (authorityId != null) + authority = (IAuthority) CMS.getSubsystem(authorityId); + + authz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ); + } + + private void setInputsIntoContext(HttpServletRequest request, IProfile profile, IProfileContext ctx) { + // passing inputs into context + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration 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 + */ + private void setInputsIntoContext(IRequest request, IProfile profile, IProfileContext ctx, Locale locale) { + // passing inputs into context + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + while (inputNames.hasMoreElements()) { + String inputName = inputNames.nextElement(); + String inputValue = ""; + CMS.debug("ProfileProcessor: setInputsIntoContext() getting input name= " + inputName); + try { + inputValue = profileInput.getValue(inputName, locale, request); + } catch (Exception e) { + CMS.debug("ProfileProcessor: setInputsIntoContext() getvalue() failed: " + e.toString()); + } + + if (inputValue != null) { + CMS.debug("ProfileProcessor: setInputsIntoContext() setting value in ctx:" + inputValue); + ctx.set(inputName, inputValue); + } else { + CMS.debug("ProfileProcessor: setInputsIntoContext() value null"); + } + } + } + } + + } + + private void setCredentialsIntoContext(HttpServletRequest request, IProfileAuthenticator authenticator, + IProfileContext ctx) { + Enumeration authIds = authenticator.getValueNames(); + + if (authIds != null) { + CMS.debug("ProfileProcessor:setCredentialsIntoContext() authNames not null"); + while (authIds.hasMoreElements()) { + String authName = authIds.nextElement(); + + CMS.debug("ProfileProcessor:setCredentialsIntoContext() authName:" + + authName); + if (request.getParameter(authName) != null) { + CMS.debug("ProfileProcessor:setCredentialsIntoContext() authName found in request"); + ctx.set(authName, request.getParameter(authName)); + } else { + CMS.debug("ProfileProcessor:setCredentialsIntoContext() authName not found in request"); + } + } + } else { + CMS.debug("ProfileProcessor: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("ProfileProcessor:: getUidFromDN(): uid found:" + v); + return v; + } else { + continue; + } + } + 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("ProfileProcessor: renewal: authToken original uid not found"); + } + } else { + CMS.debug("ProfileProcessor: 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("ProfileProcessor: 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("ProfileProcessor: renewal: authToken original uid found:" + ouid); + } else { + CMS.debug("ProfileProcessor: renewal: authToken original uid not found"); + } + } else { // through ssl client auth? + CMS.debug("ProfileProcessor: renewal: authToken uid not found:"); + // put in orig_req's uid + if (ouid != null) { + CMS.debug("ProfileProcessor: renewal: origReq uid not null:" + ouid + ". Setting authtoken"); + authToken.set("uid", ouid); + context.put(SessionContext.USER_ID, ouid); + } else { + CMS.debug("ProfileProcessor: renewal: origReq uid not found"); + // throw new EBaseException("origReq uid not found"); + } + } + + String userdn = origReq.getExtDataInString("auth_token.userdn"); + if (userdn != null) { + CMS.debug("ProfileProcessor: renewal: origReq userdn not null:" + userdn + ". Setting authtoken"); + authToken.set("userdn", userdn); + } else { + CMS.debug("ProfileProcessor: renewal: origReq userdn not found"); + // throw new EBaseException("origReq userdn not found"); + } + } else { + CMS.debug("ProfileProcessor: renewal: authToken null"); + } + return authToken; + } + + public IAuthToken authenticate(IProfileAuthenticator authenticator, + HttpServletRequest request) throws EBaseException { + AuthCredentials credentials = new AuthCredentials(); + + // build credential + Enumeration 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; + } + + private void setInputsIntoRequest(HttpServletRequest request, IProfile profile, IRequest req) { + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + if (inputNames != null) { + while (inputNames.hasMoreElements()) { + String inputName = inputNames.nextElement(); + + 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)); + } + } + } + } + } + } + } + + /* + * 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 inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + while (inputNames.hasMoreElements()) { + String inputName = inputNames.nextElement(); + String inputValue = ""; + CMS.debug("ProfileProcessor: setInputsIntoRequest() getting input name= " + inputName); + try { + inputValue = profileInput.getValue(inputName, locale, request); + } catch (Exception e) { + CMS.debug("ProfileProcessor: setInputsIntoRequest() getvalue() failed: " + e.toString()); + } + + if (inputValue != null) { + CMS.debug("ProfileProcessor: setInputsIntoRequest() setting value in ctx:" + inputValue); + req.setExtData(inputName, inputValue); + } else { + CMS.debug("ProfileProcessor: setInputsIntoRequest() value null"); + } + } + } + } + + } + + + + private void errorExit(String message) + throws EBaseException { + CMS.debug(message); + + for (String event : statEvents) { + endTiming(event); + } + throw new EBaseException(message); + } + + /** + * Process the HTTP request + *

+ * + * (Certificate Request Processed - either an automated "EE" profile based cert acceptance, or an automated "EE" + * profile based cert rejection) + *

+ * + *

    + *
  • http.param profileId ID of profile to use to process request + *
  • signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + *
+ * + * @param cmsReq the object holding the request and response information + * @exception EBaseException an error has occurred + */ + public void processEnrollment(HttpServletRequest request) throws EBaseException { + + if (CMS.debugOn()) { + printParameterValues(request); + } + + CMS.debug("ProfileProcessor: isRenewal false"); + startTiming("enrollment"); + + // if we did not configure profileId in xml file, + // then accept the user-provided one + String profileId = (this.profileID == null) ? request.getParameter("profileId") : this.profileID; + CMS.debug("ProfileProcessor: profileId " + profileId); + + IProfile profile = getProfile(profileId); + if (profile == null) { + errorExit(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); + } + + IProfileContext ctx = profile.createContext(); + IProfileAuthenticator authenticator = null; + try { + authenticator = profile.getAuthenticator(); + if (authenticator != null) { + CMS.debug("ProfileProcessor: authenticator " + authenticator.getName() + " found"); + setCredentialsIntoContext(request, authenticator, ctx); + } + } catch (EProfileException e) { + // authenticator not installed correctly + CMS.debug("ProfileProcessor: renewal: exception:" + e.toString()); + errorExit(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } + + CMS.debug("ProfileProcessor: set Inputs into profile Context"); + setInputsIntoContext(request, profile, 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("ProfileProcessor: set sslClientCertProvider"); + + // before creating the request, authenticate the request + IAuthToken authToken = null; + try { + authToken = authenticate(request, null, authenticator, context, false); + } catch (EBaseException e) { + errorExit(CMS.getUserMessage(locale, "CMS_AUTHENTICATION_ERROR")); + } + + // authentication success, now authorize + try { + authorize(profileId, profile, authToken); + } catch (EBaseException e) { + e.printStackTrace(); + errorExit(CMS.getUserMessage(locale, "CMS_AUTHORIZATION_ERROR")); + } + + /////////////////////////////////////////////// + // create and populate request + /////////////////////////////////////////////// + startTiming("request_population"); + IRequest reqs[] = null; + try { + reqs = profile.createRequests(ctx, locale); + } catch (Exception e) { + CMS.debug(e); + e.printStackTrace(); + CMS.debug("ProfileProcessor: createRequests " + e.toString()); + errorExit(e.toString()); + } + + try { + populateRequests(request, false, locale, null, null, null, profileId, profile, + ctx, authenticator, authToken, reqs); + } catch (EBaseException e) { + CMS.debug("Error in populating request: " + e); + errorExit(e.toString()); + } + endTiming("request_population"); + + /////////////////////////////////////////////// + // submit request + /////////////////////////////////////////////// + ArgSet args = new ArgSet(); + String errorCode = submitRequests(locale, profile, authToken, reqs); + String errorReason = codeToReason(locale, errorCode); + + if (errorCode != null) { + /* error stuff */ + /*if (xmlOutput) { + String requestIds = ""; + for (IRequest req : reqs) { + requestIds += " " + req.getRequestId().toString(); + } + + outputError(response, errorCode, errorReason, requestIds); + } else { + ArgList requestlist = new ArgList(); + + 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); + }*/ + + endTiming("enrollment"); + return; + } + + /////////////////////////////////////////////// + // output output list + /////////////////////////////////////////////// + + /* output stuff */ + /*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("ProfileProcessor: 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); + }*/ + + SessionContext.releaseContext(); + endTiming("enrollment"); + } + + /* + * 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 void processRenewal(HttpServletRequest request) throws EBaseException { + if (CMS.debugOn()) { + printParameterValues(request); + } + CMS.debug("ProfileProcessor: 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) ? request.getParameter("profileId") : this.profileID; + CMS.debug("processRenewal: renewProfileId " + renewProfileId); + + IProfile renewProfile = getProfile(renewProfileId); + if (renewProfile == null) { + errorExit(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", renewProfileId)); + } + + String serial = request.getParameter("serial_num"); + 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("ProfileProcessor: 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("ProfileProcessor: renewal: serial_num not found, must do ssl client auth"); + certSerial = getSerialNumberFromCert(request); + if (certSerial == null) { + errorExit(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } + } + CMS.debug("processRenewal: serial number of cert to renew:" + certSerial.toString()); + + ICertRecord rec = getCertRecord(certSerial); + if (rec == null) { + CMS.debug("processRenewal: cert record not found for serial number " + certSerial.toString()); + errorExit(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()); + errorExit(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()); + errorExit(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"); + errorExit(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } + + String profileId = origReq.getExtDataInString("profileId"); + CMS.debug("ProfileProcessor: renewal original profileId=" + profileId); + + Integer origSeqNum = origReq.getExtDataInInteger(IEnrollProfile.REQUEST_SEQ_NUM); + IProfile profile = getProfile(profileId); + if (profile == null) { + errorExit(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId)); + } + + IProfileContext ctx = profile.createContext(); + + IProfileAuthenticator authenticator = null; + IProfileAuthenticator origAuthenticator = null; + try { + authenticator = renewProfile.getAuthenticator(); + origAuthenticator = profile.getAuthenticator(); + + if (authenticator != null) { + CMS.debug("ProfileProcessor: 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("ProfileProcessor: for renewal, original authenticator " + + origAuthenticator.getName() + " found"); + setCredentialsIntoContext(request, origAuthenticator, ctx); + } + + } catch (EProfileException e) { + // authenticator not installed correctly + CMS.debug("processRenewal: exception:" + e.toString()); + errorExit(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } + + // 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("ProfileProcessor: set sslClientCertProvider"); + if (origSubjectDN != null) + context.put("origSubjectDN", origSubjectDN); + + // before creating the request, authenticate the request + IAuthToken authToken = null; + try { + authToken = authenticate(request, origReq, authenticator, context, true); + } catch (EBaseException e) { + errorExit(CMS.getUserMessage(locale, "CMS_AUTHENTICATION_ERROR")); + } + + // authentication success, now authorize + try { + authorize(profileId, renewProfile, authToken); + } catch (EBaseException e) { + e.printStackTrace(); + errorExit(CMS.getUserMessage(locale, "CMS_AUTHORIZATION_ERROR")); + } + + /////////////////////////////////////////////// + // create and populate requests + /////////////////////////////////////////////// + startTiming("request_population"); + IRequest reqs[] = null; + + try { + reqs = profile.createRequests(ctx, locale); + } catch (EProfileException e) { + CMS.debug(e); + CMS.debug("ProfileProcessor: createRequests " + e.toString()); + errorExit(e.toString()); + } catch (Throwable e) { + CMS.debug(e); + CMS.debug("ProfileProcessor: createRequests " + e.toString()); + errorExit(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } + + try { + populateRequests(request, true, locale, origNotAfter, origSubjectDN, origReq, profileId, profile, + ctx, authenticator, authToken, reqs); + } catch (EBaseException e) { + CMS.debug("Error in populating request: " + e); + errorExit(e.toString()); + return; + } + + endTiming("request_population"); + + /////////////////////////////////////////////// + // submit request + /////////////////////////////////////////////// + ArgSet args = new ArgSet(); + String errorCode = submitRequests(locale, profile, authToken, reqs); + String errorReason = codeToReason(locale, errorCode); + + if (errorCode != null) { + /* error output */ + /* + if (xmlOutput) { + String requestIds = ""; + for (IRequest req : reqs) { + requestIds += " " + req.getRequestId().toString(); + } + + outputError(response, errorCode, errorReason, requestIds); + } else { + ArgList requestlist = new ArgList(); + + 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); + }*/ + + endTiming("enrollment"); + return; + } + + /////////////////////////////////////////////// + // output output list + /////////////////////////////////////////////// + /* output stuff */ + /*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("ProfileProcessor: 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); + }*/ + + SessionContext.releaseContext(); + endTiming("enrollment"); + } + + private void authorize(String profileId, IProfile profile, IAuthToken authToken) throws EBaseException { + if (authToken != null) { + CMS.debug("ProfileProcessor authToken not null"); + + String acl = profile.getAuthzAcl(); + CMS.debug("ProfileProcessor: authz using acl: " + acl); + if (acl != null && acl.length() > 0) { + String resource = profileId + ".authz.acl"; + authorize(aclMethod, resource, authToken, acl); + } + } + } + + private IProfile getProfile(String profileId) { + if (mProfileSubId == null || mProfileSubId.equals("")) { + mProfileSubId = IProfileSubsystem.ID; + } + CMS.debug("ProfileProcessor: SubId=" + mProfileSubId); + + IProfileSubsystem ps = (IProfileSubsystem) CMS.getSubsystem(mProfileSubId); + if (ps == null) { + CMS.debug("getProfile: Profile Subsystem not found"); + return null; + } + + IProfile profile = null; + + try { + profile = ps.getProfile(profileId); + } catch (EProfileException e) { + if (profile == null) { + CMS.debug("ProfileProcessor: profile not found profileId " + profileId + " " + e.toString()); + } + } + if (profile == null) { + CMS.debug("getProfile: Profile not found: " + profileId); + return null; + } + + if (!ps.isProfileEnable(profileId)) { + CMS.debug("ProfileProcessor: Profile " + profileId + " not enabled"); + return null; + } + return profile; + } + + private String codeToReason(Locale locale, String errorCode) { + 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; + } + + private 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 reqKeys = req.getExtDataKeys(); + while (reqKeys.hasMoreElements()) { + String reqKey = reqKeys.nextElement(); + String reqVal = req.getExtDataInString(reqKey); + if (reqVal != null) { + CMS.debug("ProfileProcessor: 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("ProfileProcessor: 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("ProfileProcessor: 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("ProfileProcessor: 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("ProfileProcessor: updateRequest " + e.toString()); + } + } + return errorCode; + } + + private void populateRequests(HttpServletRequest request, 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(request, profile, req); + } + + // serial auth token into request + if (authToken != null) { + Enumeration 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("ProfileProcessor: 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, request.getParameter("profileId")); + req.setExtData(ARG_PROFILE_APPROVED_BY, profile.getApprovedBy()); + String setId = profile.getPolicySetId(req); + + if (setId == null) { + // no profile set found + CMS.debug("ProfileProcessor: no profile policy set found"); + throw new EBaseException(CMS.getUserMessage(locale, "CMS_PROFILE_NO_POLICY_SET_FOUND")); + } + + CMS.debug("ProfileProcessor profileSetid=" + setId); + req.setExtData(ARG_PROFILE_SET_ID, setId); + req.setExtData(ARG_PROFILE_REMOTE_HOST, request.getRemoteHost()); + req.setExtData(ARG_PROFILE_REMOTE_ADDR, request.getRemoteAddr()); + + CMS.debug("ProfileProcessor: request " + req.getRequestId().toString()); + + try { + CMS.debug("ProfileProcessor: 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); + } catch (EProfileException e) { + e.printStackTrace(); + CMS.debug("ProfileProcessor: EProfileException for " + req.getRequestId().toString() + + ": " + e.toString()); + throw new EBaseException(e.toString()); + } catch (Throwable e) { + CMS.debug("ProfileProcessor: populate " + e.toString()); + throw new EBaseException(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } + } + } + + private 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 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("ProfileProcessor: 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; + } + + 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); + } + + 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("ProfileProcessor: renewal: no ssl client cert chain"); + return null; + } else { // has ssl client cert + CMS.debug("ProfileProcessor: 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("ProfileProcessor: renewal: found leaf cert"); + break; + } else { + CMS.debug("ProfileProcessor: 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("ProfileProcessor: renewal: found CA cert in chain"); + break; + } // else found a ca cert, continue + } + } catch (Exception e) { + CMS.debug("ProfileProcessor: renewal: exception:" + e.toString()); + return null; + } + } + } + if (clientCert == null) { + CMS.debug("ProfileProcessor: 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("ProfileProcessor: renewal: exception:" + e.toString()); + return null; + } + + certSerial = clientCert.getSerialNumber(); + } + return certSerial; + } + + private IRequest getOriginalRequest(BigInteger certSerial, ICertRecord rec) throws EBaseException { + IAuthority authority = (IAuthority) CMS.getSubsystem(authorityId); + if (authority == null) { + CMS.debug("getOriginalRequest: Authority " + authorityId + " not found"); + return null; + } + IRequestQueue queue = authority.getRequestQueue(); + + if (queue == null) { + CMS.debug("getOriginalRequest: Request Queue of " + authorityId + " not found"); + return null; + } + + 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; + } + + CMS.debug("getOriginalRequest: request id is " + rid); + IRequest origReq = queue.findRequest(new RequestId(rid)); + return origReq; + } + + private void printParameterValues(HttpServletRequest request) { + CMS.debug("Start of ProfileProcessor Input Parameters"); + // @SuppressWarnings("unchecked") + Enumeration 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("ProfileProcessor Input Parameter " + + paramName + "='(sensitive)'"); + } else { + CMS.debug("ProfileProcessor Input Parameter " + + paramName + "='" + + request.getParameter(paramName) + "'"); + } + } + CMS.debug("End of ProfileProcessor Input Parameters"); + } + + /** + * Signed Audit Log Requester ID + * + * This method is called to obtain the "RequesterID" for + * a signed audit log message. + *

+ * + * @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 (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. + *

+ * + * @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 (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 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; + } + + public void startTiming(String event) { + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.startTiming(event, true); + } + if (statEvents == null) { + statEvents = new LinkedHashSet(); + } + statEvents.add(event); + } + + public void endTiming(String event) { + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.endTiming(event); + } + if (statEvents != null) { + statEvents.remove(event); + } + } + + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader(HDR_LANG); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } + + protected ICertRecord getCertRecord(BigInteger serialNo) { + if (authority == null || + !(authority instanceof ICertificateAuthority)) { + CMS.debug(CMS.getLogMessage("CMSGW_NON_CERT_AUTH")); + return null; + } + + ICertificateRepository certdb = ((ICertificateAuthority) authority).getCertificateRepository(); + if (certdb == null) { + CMS.debug(CMS.getLogMessage("CMSGW_CERT_DB_NULL", authority.toString())); + return null; + } + + ICertRecord certRecord = null; + try { + certRecord = certdb.readCertificateRecord(serialNo); + } catch (EBaseException e) { + CMS.debug(CMS.getLogMessage("CMSGW_NO_CERT_REC", serialNo.toString(16), e.toString())); + return null; + } + return certRecord; + } + + 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; + } + + + 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 (Exception 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 new EBaseException(e.toString()); + } + } + + 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; + } + +} 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 22a59c47..7f7f26b2 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/ProfileInput.java b/base/common/src/com/netscape/cms/servlet/profile/model/ProfileInput.java index a0aea9fd..47cfdb73 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 @@ -36,6 +36,7 @@ public class ProfileInput { } private String inputId; + @XmlJavaTypeAdapter(InputAttrsAdapter.class) public Map InputAttrs = new LinkedHashMap(); 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 1d7f8aea..8fcd1d2e 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 @@ -21,7 +21,9 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Path; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; @@ -37,6 +39,8 @@ 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.profile.ProfileProcessor; +import com.netscape.cms.servlet.profile.model.ProfileInput; import com.netscape.cms.servlet.request.CertRequestResource; /** @@ -128,11 +132,33 @@ public class CertRequestDAO extends CMSRequestDAO { * @return info for the request submitted. * @throws EBaseException */ - public CertRequestInfo submitRequest(EnrollmentRequestData data, UriInfo uriInfo) throws EBaseException { + public CertRequestInfo submitRequest(EnrollmentRequestData data, HttpServletRequest request) throws EBaseException { + HttpServletRequest extReq = createServletRequest(request, data); + ProfileProcessor processor = new ProfileProcessor(authorityId, profileID, aclMethod, locale); + if (data.getIsRenewal()) { + processor.processRenewal(extReq); + } else { + processor.processEnrollment(extReq); + } + //TODO handle good data return. + } + + private HttpServletRequest createServletRequest(HttpServletRequest request, EnrollmentRequestData data) { + ExtendableHttpRequest extReq = new ExtendableHttpRequest(request); + extReq.addParameter("profileId", data.getProfileId()); + extReq.addParameter("serial_num", data.getSerialNum()); + + for (ProfileInput input: data.inputs) { + Map attrs = input.getAttributes(); + for (Map.Entry entry: attrs.entrySet()) { + extReq.addParameter(entry.getKey(), entry.getValue()); + } + } - //TODO perform actual profile request. + // TODO - add authenticator entries + return extReq; - throw new EBaseException("Not implemented."); + // TODO Auto-generated method stub } public void approveRequest(RequestId id) throws EBaseException { 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 f2979ebc..aa2f4a33 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 @@ -50,6 +50,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,6 +58,9 @@ public class EnrollmentRequestData { @XmlElement protected boolean isRenewal; + @XmlElement + protected String serialNum; // used for one type of renewal + @XmlElement(name = "Input") protected List inputs = new ArrayList(); @@ -66,6 +70,7 @@ public class EnrollmentRequestData { public EnrollmentRequestData(MultivaluedMap form) { profileId = form.getFirst(PROFILE_ID); String renewalStr = form.getFirst(RENEWAL); + serialNum = form.getFirst(SERIAL_NUM); isRenewal = new Boolean(renewalStr); @@ -199,4 +204,12 @@ public class EnrollmentRequestData { } } + public String getSerialNum() { + return serialNum; + } + + public void setSerialNum(String serialNum) { + this.serialNum = serialNum; + } + } diff --git a/base/common/src/com/netscape/cms/servlet/request/model/ExtendableHttpRequest.java b/base/common/src/com/netscape/cms/servlet/request/model/ExtendableHttpRequest.java new file mode 100644 index 00000000..33c13bb1 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/ExtendableHttpRequest.java @@ -0,0 +1,29 @@ +package com.netscape.cms.servlet.request.model; + +import java.util.HashMap; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +public class ExtendableHttpRequest extends HttpServletRequestWrapper { + + private HashMap params = new HashMap(); + + public ExtendableHttpRequest(HttpServletRequest request) { + super(request); + } + + public String getParameter(String name) { + // if we added one, return that one + if (params.get(name) != null) { + return params.get(name); + } + // otherwise return what's in the original request + HttpServletRequest req = (HttpServletRequest) super.getRequest(); + return req.getParameter(name); + } + + public void addParameter(String name, String value) { + if (value != null) params.put(name, value); + } +} -- cgit