summaryrefslogtreecommitdiffstats
path: root/base/common/src/com/netscape/cms/servlet/processors/Processor.java
diff options
context:
space:
mode:
authorAde Lee <alee@redhat.com>2012-05-13 23:04:36 -0400
committerAde Lee <alee@redhat.com>2012-07-03 13:58:45 -0400
commit9ce810c0b2fef9f70178dbeee8a3523755a2a260 (patch)
treea25cd9e9969898506ed2a4cb17a3cfbeb68496cf /base/common/src/com/netscape/cms/servlet/processors/Processor.java
parent0f3451befbc14bd6ec29d9e1e3845f970f288653 (diff)
downloadpki-9ce810c0b2fef9f70178dbeee8a3523755a2a260.tar.gz
pki-9ce810c0b2fef9f70178dbeee8a3523755a2a260.tar.xz
pki-9ce810c0b2fef9f70178dbeee8a3523755a2a260.zip
Adding restful interface to create certificate requests and issue certificates.
Refactored ProfileSubmitServlet to make the flow clearer. Both the legacy servlets and the new RESTful servlets use common ProfileProcessor objects that contain the main business logic, so that the amount of duplicated code is minimized. Refactored ProfileProcessServlet to use the new common classes. Addressed review comments. Removed an unneeded class and reverted some unneeded jaxb annotations. Added factory methods.
Diffstat (limited to 'base/common/src/com/netscape/cms/servlet/processors/Processor.java')
-rw-r--r--base/common/src/com/netscape/cms/servlet/processors/Processor.java1259
1 files changed, 1259 insertions, 0 deletions
diff --git a/base/common/src/com/netscape/cms/servlet/processors/Processor.java b/base/common/src/com/netscape/cms/servlet/processors/Processor.java
new file mode 100644
index 000000000..d5893a479
--- /dev/null
+++ b/base/common/src/com/netscape/cms/servlet/processors/Processor.java
@@ -0,0 +1,1259 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.processors;
+
+import java.math.BigInteger;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+import java.util.Map.Entry;
+import java.util.StringTokenizer;
+
+import javax.servlet.http.HttpServletRequest;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.IAuthzSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.base.Nonces;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.util.IStatsSubsystem;
+import com.netscape.cms.servlet.common.AuthCredentials;
+import com.netscape.cms.servlet.common.CMSGateway;
+import com.netscape.cms.servlet.common.ServletUtils;
+import com.netscape.cmsutil.util.Utils;
+
+public class Processor {
+
+ public final static String ARG_AUTH_TOKEN = "auth_token";
+ public final static String ARG_REQUEST_OWNER = "requestOwner";
+ public final static String HDR_LANG = "accept-language";
+ public final static String ARG_PROFILE = "profile";
+ public final static String ARG_REQUEST_NOTES = "requestNotes";
+ public final static String ARG_PROFILE_ID = "profileId";
+ public final static String ARG_RENEWAL_PROFILE_ID = "rprofileId";
+ public final static String ARG_PROFILE_IS_ENABLED = "profileIsEnable";
+ public final static String ARG_PROFILE_IS_VISIBLE = "profileIsVisible";
+ public final static String ARG_PROFILE_ENABLED_BY = "profileEnableBy";
+ public final static String ARG_PROFILE_APPROVED_BY = "profileApprovedBy";
+ public final static String ARG_PROFILE_NAME = "profileName";
+ public final static String ARG_PROFILE_DESC = "profileDesc";
+ public final static String ARG_PROFILE_REMOTE_HOST = "profileRemoteHost";
+ public final static String ARG_PROFILE_REMOTE_ADDR = "profileRemoteAddr";
+ public final static String ARG_PROFILE_SET_ID = "profileSetId";
+ public final static String ARG_OUTPUT_LIST = "outputList";
+ public final static String ARG_OUTPUT_ID = "outputId";
+ public final static String ARG_OUTPUT_SYNTAX = "outputSyntax";
+ public final static String ARG_OUTPUT_CONSTRAINT = "outputConstraint";
+ public final static String ARG_OUTPUT_NAME = "outputName";
+ public final static String ARG_OUTPUT_VAL = "outputVal";
+ public final static String ARG_REQUEST_LIST = "requestList";
+ public final static String ARG_REQUEST_ID = "requestId";
+ public final static String ARG_REQUEST_TYPE = "requestType";
+ public final static String ARG_REQUEST_STATUS = "requestStatus";
+ public final static String ARG_REQUEST_CREATION_TIME = "requestCreationTime";
+ public final static String ARG_REQUEST_MODIFICATION_TIME = "requestModificationTime";
+ public final static String ARG_REQUEST_NONCE = "nonce";
+ public final static String ARG_OP = "op";
+ public final static String ARG_REQUESTS = "requests";
+ public final static String ARG_ERROR_CODE = "errorCode";
+ public final static String ARG_ERROR_REASON = "errorReason";
+ public final static String CERT_ATTR = "javax.servlet.request.X509Certificate";
+
+ // servlet config constants
+ public static final String PROFILE_ID = "profileId";
+ public static final String AUTH_ID = "authId";
+ public static final String ACL_METHOD = "aclMethod";
+ public static final String AUTHZ_RESOURCE_NAME = "authzResourceName";
+ public static final String AUTH_MGR = "authMgr";
+ public static final String AUTHZ_MGR = "authzMgr";
+ public static final String GET_CLIENT_CERT = "getClientCert";
+ public static final String ACL_INFO = "ACLinfo";
+ public static final String AUTHORITY_ID = "authorityId";
+ public static final String PROFILE_SUB_ID = "profileSubId";
+
+ public final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED =
+ "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5";
+ public final static String LOGGING_SIGNED_AUDIT_AUTH_FAIL =
+ "LOGGING_SIGNED_AUDIT_AUTH_FAIL_4";
+ public final static String LOGGING_SIGNED_AUDIT_AUTH_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_AUTH_SUCCESS_3";
+ public final static String LOGGING_SIGNED_AUDIT_AUTHZ_FAIL =
+ "LOGGING_SIGNED_AUDIT_AUTHZ_FAIL_4";
+ public final static String LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS_4";
+ public final static String LOGGING_SIGNED_AUDIT_ROLE_ASSUME =
+ "LOGGING_SIGNED_AUDIT_ROLE_ASSUME_3";
+ public final static String SIGNED_AUDIT_CERT_REQUEST_REASON =
+ "requestNotes";
+
+ protected String profileID;
+ protected String profileSubId;
+ protected String aclMethod;
+ protected String authzResourceName;
+ protected String authMgr;
+ protected String getClientCert = "false";
+ protected Nonces nonces;
+ protected Locale locale;
+
+ // subsystems
+ protected ICertificateAuthority authority = (ICertificateAuthority) CMS.getSubsystem("ca");
+ protected IAuthzSubsystem authz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ);
+ protected IUGSubsystem ug = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+ protected IRequestQueue queue;
+ protected IProfileSubsystem ps;
+ protected ICertificateRepository certdb;
+
+ //logging and stats
+ protected ILogger signedAuditLogger = CMS.getSignedAuditLogger();
+ protected LinkedHashSet<String> statEvents = new LinkedHashSet<String>();
+
+ public Processor(String id, Locale locale) throws EPropertyNotFound, EBaseException {
+ IConfigStore cs = CMS.getConfigStore().getSubStore("profile." + id);
+ this.locale = locale;
+ this.profileID = cs.getString(PROFILE_ID, "").isEmpty() ? null : cs.getString(PROFILE_ID);
+ this.authzResourceName = cs.getString(AUTHZ_RESOURCE_NAME, "").isEmpty() ? null :
+ cs.getString(AUTHZ_RESOURCE_NAME);
+ this.authMgr = cs.getString(AUTH_MGR, "").isEmpty() ? null : cs.getString(AUTH_MGR);
+ this.getClientCert = cs.getString(GET_CLIENT_CERT, "").isEmpty() ? "false" : cs.getString(GET_CLIENT_CERT);
+ this.profileSubId = cs.getString(PROFILE_SUB_ID, "").isEmpty() ? IProfileSubsystem.ID :
+ cs.getString(PROFILE_SUB_ID);
+
+ String aclInfo = cs.getString(ACL_INFO, "").isEmpty() ? null : cs.getString(ACL_INFO);
+ String authzMgr = cs.getString(AUTHZ_MGR, "").isEmpty() ? null : cs.getString(AUTHZ_MGR);
+ this.aclMethod = ServletUtils.getACLMethod(aclInfo, authzMgr, id);
+
+ // currently unused but in servlet config
+ // authId = cs.getString(AUTH_ID, "").isEmpty() ? null : cs.getString(AUTH_ID);
+
+ if (authority == null) {
+ throw new EBaseException("CertProcessor: authority is null");
+ }
+
+ if (authority.noncesEnabled()) {
+ nonces = authority.getNonces();
+ }
+
+ queue = authority.getRequestQueue();
+ if (queue == null) {
+ throw new EBaseException("CertProcessor: cannot get request queue");
+ }
+
+ if (profileSubId == null || profileSubId.equals("")) {
+ profileSubId = IProfileSubsystem.ID;
+ }
+
+ ps = (IProfileSubsystem) CMS.getSubsystem(profileSubId);
+ if (ps == null) {
+ throw new EBaseException("CertProcessor: Profile Subsystem not found");
+ }
+
+ certdb = authority.getCertificateRepository();
+ if (certdb == null) {
+ throw new EBaseException("CertProcessor: Certificate repository not found");
+ }
+ }
+
+ /******************************************
+ * Stats - to be moved to Stats module
+ ******************************************/
+
+ public void startTiming(String event) {
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ statsSub.startTiming(event, true);
+ }
+ statEvents.add(event);
+ }
+
+ public void endTiming(String event) {
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ statsSub.endTiming(event);
+ }
+ statEvents.remove(event);
+ }
+
+ public void endAllEvents() {
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ Iterator<String> iter = statEvents.iterator();
+ while (iter.hasNext()) {
+ String event = iter.next();
+ statsSub.endTiming(event);
+ iter.remove();
+ }
+ }
+ }
+
+ /******************************************
+ * Utility Functions
+ ******************************************/
+
+ public IRequest getRequest(String rid) throws EBaseException {
+ IRequest request = queue.findRequest(new RequestId(rid));
+ return request;
+ }
+
+ protected IRequest getOriginalRequest(BigInteger certSerial, ICertRecord rec) throws EBaseException {
+ MetaInfo metaInfo = (MetaInfo) rec.get(ICertRecord.ATTR_META_INFO);
+ if (metaInfo == null) {
+ CMS.debug("getOriginalRequest: cert record locating MetaInfo failed for serial number "
+ + certSerial.toString());
+ return null;
+ }
+
+ String rid = (String) metaInfo.get(ICertRecord.META_REQUEST_ID);
+ if (rid == null) {
+ CMS.debug("getOriginalRequest: cert record locating request id in MetaInfo failed " +
+ "for serial number " + certSerial.toString());
+ return null;
+ }
+
+ IRequest request = queue.findRequest(new RequestId(rid));
+ return request;
+ }
+
+ protected void printParameterValues(HashMap<String, String> data) {
+ CMS.debug("Start of CertProcessor Input Parameters");
+
+ for (Entry<String, String> entry : data.entrySet()) {
+ String paramName = entry.getKey();
+ // added this facility so that password can be hidden,
+ // all sensitive parameters should be prefixed with
+ // __ (double underscores); however, in the event that
+ // a security parameter slips through, we perform multiple
+ // additional checks to insure that it is NOT displayed
+ if (paramName.startsWith("__") ||
+ paramName.endsWith("password") ||
+ paramName.endsWith("passwd") ||
+ paramName.endsWith("pwd") ||
+ paramName.equalsIgnoreCase("admin_password_again") ||
+ paramName.equalsIgnoreCase("directoryManagerPwd") ||
+ paramName.equalsIgnoreCase("bindpassword") ||
+ paramName.equalsIgnoreCase("bindpwd") ||
+ paramName.equalsIgnoreCase("passwd") ||
+ paramName.equalsIgnoreCase("password") ||
+ paramName.equalsIgnoreCase("pin") ||
+ paramName.equalsIgnoreCase("pwd") ||
+ paramName.equalsIgnoreCase("pwdagain") ||
+ paramName.equalsIgnoreCase("uPasswd")) {
+ CMS.debug("CertProcessor Input Parameter " + paramName + "='(sensitive)'");
+ } else {
+ CMS.debug("CertProcessor Input Parameter " + paramName + "='" + entry.getValue() + "'");
+ }
+ }
+
+ CMS.debug("End of CertProcessor Input Parameters");
+ }
+
+ protected StringBuffer escapeValueRfc1779(String v, boolean doubleEscape) {
+ StringBuffer result = new StringBuffer();
+
+ // Do we need to escape any characters
+ for (int i = 0; i < v.length(); i++) {
+ int c = v.charAt(i);
+ if (c == ',' || c == '=' || c == '+' || c == '<' ||
+ c == '>' || c == '#' || c == ';' || c == '\r' ||
+ c == '\n' || c == '\\' || c == '"') {
+ if ((c == 0x5c) && ((i + 1) < v.length())) {
+ int nextC = v.charAt(i + 1);
+ if ((c == 0x5c) && (nextC == ',' || nextC == '=' || nextC == '+' ||
+ nextC == '<' || nextC == '>' || nextC == '#' ||
+ nextC == ';' || nextC == '\r' || nextC == '\n' ||
+ nextC == '\\' || nextC == '"')) {
+ if (doubleEscape)
+ result.append('\\');
+ } else {
+ result.append('\\');
+ if (doubleEscape)
+ result.append('\\');
+ }
+ } else {
+ result.append('\\');
+ if (doubleEscape)
+ result.append('\\');
+ }
+ }
+ if (c == '\r') {
+ result.append("0D");
+ } else if (c == '\n') {
+ result.append("0A");
+ } else {
+ result.append((char) c);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * get ssl client authenticated certificate
+ */
+ public static X509Certificate getSSLClientCertificate(HttpServletRequest httpReq)
+ throws EBaseException {
+ X509Certificate cert = null;
+
+ CMS.debug(CMS.getLogMessage("CMSGW_GETTING_SSL_CLIENT_CERT"));
+
+ // iws60 support Java Servlet Spec V2.2, attribute
+ // javax.servlet.request.X509Certificate now contains array
+ // of X509Certificates instead of one X509Certificate object
+ X509Certificate[] allCerts = (X509Certificate[]) httpReq.getAttribute(CERT_ATTR);
+
+ if (allCerts == null || allCerts.length == 0) {
+ throw new EBaseException("You did not provide a valid certificate for this operation");
+ }
+
+ cert = allCerts[0];
+
+ if (cert == null) {
+ // just don't have a cert.
+ CMS.debug(CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL"));
+ return null;
+ }
+
+ // convert to sun's x509 cert interface.
+ try {
+ byte[] certEncoded = cert.getEncoded();
+ cert = new X509CertImpl(certEncoded);
+ } catch (CertificateEncodingException e) {
+ CMS.debug(CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL_ENCODE", e.getMessage()));
+ return null;
+ } catch (CertificateException e) {
+ CMS.debug(CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL_DECODE", e.getMessage()));
+ return null;
+ }
+ return cert;
+ }
+
+ protected static Hashtable<String, String> toHashtable(HttpServletRequest req) {
+ Hashtable<String, String> httpReqHash = new Hashtable<String, String>();
+ Enumeration<?> names = req.getParameterNames();
+
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+
+ httpReqHash.put(name, req.getParameter(name));
+ }
+ return httpReqHash;
+ }
+
+ /******************************************
+ * AUTHENTICATION FUNCTIONS (move to Realm?)
+ ******************************************/
+
+ /*
+ * authenticate for renewal - more to add necessary params/values
+ * to the session context
+ */
+ public IAuthToken authenticate(IProfileAuthenticator authenticator,
+ HttpServletRequest request, IRequest origReq, SessionContext context) throws EBaseException
+ {
+ IAuthToken authToken = authenticate(authenticator, request);
+ // For renewal, fill in necessary params
+ if (authToken != null) {
+ String ouid = origReq.getExtDataInString("auth_token.uid");
+ // if the orig cert was manually approved, then there was
+ // no auth token uid. Try to get the uid from the cert dn
+ // itself, if possible
+ if (ouid == null) {
+ String sdn = (String) context.get("origSubjectDN");
+ if (sdn != null) {
+ ouid = getUidFromDN(sdn);
+ if (ouid != null)
+ CMS.debug("CertProcessor: renewal: authToken original uid not found");
+ }
+ } else {
+ CMS.debug("CertProcessor: renewal: authToken original uid found in orig request auth_token");
+ }
+ String auid = authToken.getInString("uid");
+ if (auid != null) { // not through ssl client auth
+ CMS.debug("CertProcessor: renewal: authToken uid found:" + auid);
+ // authenticated with uid
+ // put "orig_req.auth_token.uid" so that authz with
+ // UserOrigReqAccessEvaluator will work
+ if (ouid != null) {
+ context.put("orig_req.auth_token.uid", ouid);
+ CMS.debug("CertProcessor: renewal: authToken original uid found:" + ouid);
+ } else {
+ CMS.debug("CertProcessor: renewal: authToken original uid not found");
+ }
+ } else { // through ssl client auth?
+ CMS.debug("CertProcessor: renewal: authToken uid not found:");
+ // put in orig_req's uid
+ if (ouid != null) {
+ CMS.debug("CertProcessor: renewal: origReq uid not null:" + ouid + ". Setting authtoken");
+ authToken.set("uid", ouid);
+ context.put(SessionContext.USER_ID, ouid);
+ } else {
+ CMS.debug("CertProcessor: renewal: origReq uid not found");
+ // throw new EBaseException("origReq uid not found");
+ }
+ }
+
+ String userdn = origReq.getExtDataInString("auth_token.userdn");
+ if (userdn != null) {
+ CMS.debug("CertProcessor: renewal: origReq userdn not null:" + userdn + ". Setting authtoken");
+ authToken.set("userdn", userdn);
+ } else {
+ CMS.debug("CertProcessor: renewal: origReq userdn not found");
+ // throw new EBaseException("origReq userdn not found");
+ }
+ } else {
+ CMS.debug("CertProcessor: renewal: authToken null");
+ }
+ return authToken;
+ }
+
+ public IAuthToken authenticate(IProfileAuthenticator authenticator,
+ HttpServletRequest request) throws EBaseException {
+ AuthCredentials credentials = new AuthCredentials();
+
+ // build credential
+ Enumeration<String> authNames = authenticator.getValueNames();
+
+ if (authNames != null) {
+ while (authNames.hasMoreElements()) {
+ String authName = authNames.nextElement();
+
+ credentials.set(authName, request.getParameter(authName));
+ }
+ }
+
+ credentials.set("clientHost", request.getRemoteHost());
+ IAuthToken authToken = authenticator.authenticate(credentials);
+
+ SessionContext sc = SessionContext.getContext();
+ if (sc != null) {
+ sc.put(SessionContext.AUTH_MANAGER_ID, authenticator.getName());
+ String userid = authToken.getInString(IAuthToken.USER_ID);
+ if (userid != null) {
+ sc.put(SessionContext.USER_ID, userid);
+ }
+ }
+
+ return authToken;
+ }
+
+ public IAuthToken authenticate(HttpServletRequest request, IRequest origReq, IProfileAuthenticator authenticator,
+ SessionContext context, boolean isRenewal) throws EBaseException {
+ startTiming("profile_authentication");
+
+ IAuthToken authToken = null;
+ if (authenticator != null) {
+ CMS.debug("authenticate: authentication required.");
+ String uid_cred = "Unidentified";
+ String uid_attempted_cred = "Unidentified";
+ Enumeration<String> authIds = authenticator.getValueNames();
+ //Attempt to possibly fetch attempted uid, may not always be available.
+ if (authIds != null) {
+ while (authIds.hasMoreElements()) {
+ String authName = authIds.nextElement();
+ String value = request.getParameter(authName);
+ if (value != null) {
+ if (authName.equals("uid")) {
+ uid_attempted_cred = value;
+ }
+ }
+ }
+ }
+
+ String authSubjectID = auditSubjectID();
+ String authMgrID = authenticator.getName();
+ String auditMessage = null;
+ try {
+ if (isRenewal) {
+ authToken = authenticate(authenticator, request, origReq, context);
+ } else {
+ authToken = authenticate(authenticator, request);
+ }
+ } catch (EBaseException e) {
+ CMS.debug("CertProcessor: authentication error " + e.toString());
+
+ authSubjectID += " : " + uid_cred;
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ authSubjectID,
+ ILogger.FAILURE,
+ authMgrID,
+ uid_attempted_cred);
+ audit(auditMessage);
+
+ throw e;
+ }
+
+ //Log successful authentication
+ //Attempt to get uid from authToken, most tokens respond to the "uid" cred.
+ uid_cred = authToken.getInString("uid");
+
+ if (uid_cred == null || uid_cred.length() == 0) {
+ uid_cred = "Unidentified";
+ }
+
+ authSubjectID = authSubjectID + " : " + uid_cred;
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_SUCCESS,
+ authSubjectID,
+ ILogger.SUCCESS,
+ authMgrID);
+
+ audit(auditMessage);
+ }
+ endTiming("profile_authentication");
+ return authToken;
+ }
+
+ public IAuthToken authenticate(HttpServletRequest httpReq)
+ throws EBaseException {
+ return authenticate(httpReq, authMgr);
+ }
+
+ public static void saveAuthToken(IAuthToken token, IRequest req) {
+ if (token != null && req != null)
+ req.setExtData(IRequest.AUTH_TOKEN, token);
+
+ // # 56230 - expose auth token parameters to the policy predicate
+ if (token != null && req != null) {
+ Enumeration<String> e = token.getElements();
+ while (e.hasMoreElements()) {
+ String n = e.nextElement();
+ String[] x1 = token.getInStringArray(n);
+ if (x1 != null) {
+ for (int i = 0; i < x1.length; i++) {
+ CMS.debug("Setting " + IRequest.AUTH_TOKEN + "-" + n +
+ "(" + i + ")=" + x1[i]);
+ req.setExtData(IRequest.AUTH_TOKEN + "-" + n + "(" + i + ")",
+ x1[i]);
+ }
+ } else {
+ String x = token.getInString(n);
+ if (x != null) {
+ CMS.debug("Setting " + IRequest.AUTH_TOKEN + "-" + n + "=" + x);
+ req.setExtData(IRequest.AUTH_TOKEN + "-" + n, x);
+ }
+ }
+ } // while
+ } // if
+ }
+
+ public IAuthToken authenticate(HttpServletRequest httpReq, String authMgrName)
+ throws EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = ILogger.UNIDENTIFIED;
+ String auditAuthMgrID = ILogger.UNIDENTIFIED;
+ String auditUID = ILogger.UNIDENTIFIED;
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ IArgBlock httpArgs = CMS.createArgBlock(toHashtable(httpReq));
+ SessionContext ctx = SessionContext.getContext();
+ String ip = httpReq.getRemoteAddr();
+ CMS.debug("IP: " + ip);
+
+ if (ip != null) {
+ ctx.put(SessionContext.IPADDRESS, ip);
+ }
+ if (authMgrName != null) {
+ CMS.debug("AuthMgrName: " + authMgrName);
+ ctx.put(SessionContext.AUTH_MANAGER_ID, authMgrName);
+ }
+ // put locale into session context
+ ctx.put(SessionContext.LOCALE, locale);
+
+ //
+ // check ssl client authentication if specified.
+ //
+ X509Certificate clientCert = null;
+
+ if (getClientCert != null && getClientCert.equals("true")) {
+ CMS.debug("CMSServlet: retrieving SSL certificate");
+ clientCert = getSSLClientCertificate(httpReq);
+ }
+
+ //
+ // check authentication by auth manager if any.
+ //
+ if (authMgrName == null) {
+
+ // Fixed Blackflag Bug #613900: Since this code block does
+ // NOT actually constitute an authentication failure, but
+ // rather the case in which a given servlet has been correctly
+ // configured to NOT require an authentication manager, the
+ // audit message called LOGGING_SIGNED_AUDIT_AUTH_FAIL has
+ // been removed.
+
+ CMS.debug("CMSServlet: no authMgrName");
+ return null;
+ } else {
+ // save the "Subject DN" of this certificate in case it
+ // must be audited as an authentication failure
+ if (clientCert == null) {
+ CMS.debug("CMSServlet: no client certificate found");
+ } else {
+ String certUID = clientCert.getSubjectDN().getName();
+ CMS.debug("CMSServlet: certUID=" + certUID);
+
+ if (certUID != null) {
+ certUID = certUID.trim();
+
+ if (!(certUID.equals(""))) {
+ // reset the "auditUID"
+ auditUID = certUID;
+ }
+ }
+ }
+
+ // reset the "auditAuthMgrID"
+ auditAuthMgrID = authMgrName;
+ }
+ AuthToken authToken = CMSGateway.checkAuthManager(httpReq,
+ httpArgs,
+ clientCert,
+ authMgrName);
+ if (authToken == null) {
+ return null;
+ }
+ String userid = authToken.getInString(IAuthToken.USER_ID);
+
+ CMS.debug("CMSServlet: userid=" + userid);
+
+ if (userid != null) {
+ ctx.put(SessionContext.USER_ID, userid);
+ }
+
+ // reset the "auditSubjectID"
+ auditSubjectID = auditSubjectID();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditAuthMgrID);
+
+ audit(auditMessage);
+
+ return authToken;
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditAuthMgrID,
+ auditUID);
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ }
+ }
+
+ String getUidFromDN(String userdn) {
+ StringTokenizer st = new StringTokenizer(userdn, ",");
+ while (st.hasMoreTokens()) {
+ String t = st.nextToken();
+ int i = t.indexOf("=");
+
+ if (i == -1) {
+ continue;
+ }
+ String n = t.substring(0, i);
+ if (n.equalsIgnoreCase("uid")) {
+ String v = t.substring(i + 1);
+ CMS.debug("CertProcessor:: getUidFromDN(): uid found:" + v);
+ return v;
+ } else {
+ continue;
+ }
+ }
+ return null;
+ }
+
+ /******************************************
+ * AUTHZ FNCTIONS (to be moved to Realm?)
+ *****************************************/
+
+ public AuthzToken authorize(String authzMgrName, String resource, IAuthToken authToken,
+ String exp) throws EBaseException {
+ AuthzToken authzToken = null;
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditGroupID = auditGroupID();
+ String auditACLResource = resource;
+ String auditOperation = "enroll";
+
+ try {
+ authzToken = authz.authorize(authzMgrName, authToken, exp);
+ if (authzToken != null) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditGroupID);
+
+ audit(auditMessage);
+ } else {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditGroupID);
+
+ audit(auditMessage);
+ }
+ return authzToken;
+ } catch (EBaseException e) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditGroupID);
+
+ audit(auditMessage);
+ throw e;
+ }
+ }
+
+ /**
+ * Authorize must occur after Authenticate
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_FAIL used when authorization has failed
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS used when authorization is successful
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_ROLE_ASSUME used when user assumes a role (in current CS that's when one
+ * accesses a role port)
+ * </ul>
+ *
+ * @param authzMgrName string representing the name of the authorization
+ * manager
+ * @param authToken the authentication token
+ * @param resource a string representing the ACL resource id as defined in
+ * the ACL resource list
+ * @param operation a string representing one of the operations as defined
+ * within the ACL statement (e. g. - "read" for an ACL statement containing
+ * "(read,write)")
+ * @exception EBaseException an error has occurred
+ * @return the authorization token
+ */
+ public AuthzToken authorize(String authzMgrName, IAuthToken authToken,
+ String resource, String operation) {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditGroupID = auditGroupID();
+ String auditID = auditSubjectID;
+ String auditACLResource = resource;
+ String auditOperation = operation;
+
+ SessionContext auditContext = SessionContext.getExistingContext();
+ String authManagerId = null;
+
+ if (auditContext != null) {
+ authManagerId = (String) auditContext.get(SessionContext.AUTH_MANAGER_ID);
+
+ if (authManagerId != null && authManagerId.equals("TokenAuth")) {
+ if (auditSubjectID.equals(ILogger.NONROLEUSER) ||
+ auditSubjectID.equals(ILogger.UNIDENTIFIED)) {
+ CMS.debug("CMSServlet: in authorize... TokenAuth auditSubjectID unavailable, changing to auditGroupID");
+ auditID = auditGroupID;
+ }
+ }
+ }
+
+ // "normalize" the "auditACLResource" value
+ if (auditACLResource != null) {
+ auditACLResource = auditACLResource.trim();
+ }
+
+ // "normalize" the "auditOperation" value
+ if (auditOperation != null) {
+ auditOperation = auditOperation.trim();
+ }
+
+ if (authzMgrName == null) {
+ // Fixed Blackflag Bug #613900: Since this code block does
+ // NOT actually constitute an authorization failure, but
+ // rather the case in which a given servlet has been correctly
+ // configured to NOT require an authorization manager, the
+ // audit message called LOGGING_SIGNED_AUDIT_AUTHZ_FAIL and
+ // the audit message called LOGGING_SIGNED_AUDIT_ROLE_ASSUME
+ // (marked as a failure) have been removed.
+
+ return null;
+ }
+
+ try {
+ AuthzToken authzTok = authz.authorize(authzMgrName,
+ authToken,
+ resource,
+ operation);
+
+ if (authzTok != null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditID,
+ ILogger.SUCCESS,
+ auditGroups(auditSubjectID));
+
+ audit(auditMessage);
+ } else {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditID,
+ ILogger.FAILURE,
+ auditGroups(auditSubjectID));
+
+ audit(auditMessage);
+ }
+
+ return authzTok;
+ } catch (Exception eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditID,
+ ILogger.FAILURE,
+ auditGroups(auditSubjectID));
+
+ audit(auditMessage);
+
+ return null;
+ }
+ }
+
+ public void authorize(String profileId, IProfile profile, IAuthToken authToken) throws EBaseException {
+ if (authToken != null) {
+ CMS.debug("CertProcessor authToken not null");
+
+ String acl = profile.getAuthzAcl();
+ CMS.debug("CertProcessor: authz using acl: " + acl);
+ if (acl != null && acl.length() > 0) {
+ String resource = profileId + ".authz.acl";
+ authorize(aclMethod, resource, authToken, acl);
+ }
+ }
+ }
+
+ /******************************************
+ * AUDIT FUNCTIONS (to be moved to Auditor?)
+ ******************************************/
+ protected void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+
+ if (signedAuditLogger == null) {
+ return;
+ }
+
+ signedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+
+ /**
+ * Signed Audit Log Requester ID
+ *
+ * This method is called to obtain the "RequesterID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param request the actual request
+ * @return id string containing the signed audit log message RequesterID
+ */
+ protected String auditRequesterID(IRequest request) {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) {
+ return null;
+ }
+
+ String requesterID = ILogger.UNIDENTIFIED;
+
+ if (request != null) {
+ // overwrite "requesterID" if and only if "id" != null
+ String id = request.getRequestId().toString();
+
+ if (id != null) {
+ requesterID = id.trim();
+ }
+ }
+
+ return requesterID;
+ }
+
+ /**
+ * Signed Audit Log Info Certificate Value
+ *
+ * This method is called to obtain the certificate from the passed in
+ * "X509CertImpl" for a signed audit log message.
+ * <P>
+ *
+ * @param request request containing an X509CertImpl
+ * @return cert string containing the certificate
+ */
+ protected String auditInfoCertValue(IRequest request) {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) {
+ return null;
+ }
+
+ X509CertImpl x509cert = request.getExtDataInCert(
+ IEnrollProfile.REQUEST_ISSUED_CERT);
+
+ if (x509cert == null) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ byte rawData[] = null;
+
+ try {
+ rawData = x509cert.getEncoded();
+ } catch (CertificateEncodingException e) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ String cert = null;
+
+ // convert "rawData" into "base64Data"
+ if (rawData != null) {
+ String base64Data = null;
+
+ base64Data = Utils.base64encode(rawData).trim();
+
+ // extract all line separators from the "base64Data"
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < base64Data.length(); i++) {
+ if (!Character.isWhitespace(base64Data.charAt(i))) {
+ sb.append(base64Data.charAt(i));
+
+ }
+ }
+ cert = sb.toString();
+ }
+
+ if (cert != null) {
+ cert = cert.trim();
+
+ if (cert.equals("")) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ } else {
+ return cert;
+ }
+ } else {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+
+ protected String auditSubjectID() {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) {
+ return null;
+ }
+
+ CMS.debug("CMSServlet: in auditSubjectID");
+ String subjectID = null;
+
+ // Initialize subjectID
+ SessionContext auditContext = SessionContext.getExistingContext();
+
+ CMS.debug("CMSServlet: auditSubjectID auditContext " + auditContext);
+ if (auditContext != null) {
+ subjectID = (String)
+ auditContext.get(SessionContext.USER_ID);
+
+ CMS.debug("CMSServlet auditSubjectID: subjectID: " + subjectID);
+ if (subjectID != null) {
+ subjectID = subjectID.trim();
+ } else {
+ subjectID = ILogger.NONROLEUSER;
+ }
+ } else {
+ subjectID = ILogger.UNIDENTIFIED;
+ }
+
+ return subjectID;
+ }
+
+ protected String auditGroupID() {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) {
+ return null;
+ }
+
+ CMS.debug("CMSServlet: in auditGroupID");
+ String groupID = null;
+
+ // Initialize groupID
+ SessionContext auditContext = SessionContext.getExistingContext();
+
+ CMS.debug("CMSServlet: auditGroupID auditContext " + auditContext);
+ if (auditContext != null) {
+ groupID = (String)
+ auditContext.get(SessionContext.GROUP_ID);
+
+ CMS.debug("CMSServlet auditGroupID: groupID: " + groupID);
+ if (groupID != null) {
+ groupID = groupID.trim();
+ } else {
+ groupID = ILogger.NONROLEUSER;
+ }
+ } else {
+ groupID = ILogger.UNIDENTIFIED;
+ }
+
+ return groupID;
+ }
+
+ /**
+ * Signed Audit Log Info Value
+ *
+ * This method is called to obtain the "reason" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param request the actual request
+ * @return reason string containing the signed audit log message reason
+ */
+ protected String auditInfoValue(IRequest request) {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) {
+ return null;
+ }
+
+ String reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+
+ if (request != null) {
+ // overwrite "reason" if and only if "info" != null
+ String info =
+ request.getExtDataInString(SIGNED_AUDIT_CERT_REQUEST_REASON);
+
+ if (info != null) {
+ reason = info.trim();
+
+ // overwrite "reason" if and only if "reason" is empty
+ if (reason.equals("")) {
+ reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+ }
+
+ return reason;
+ }
+
+ /**
+ * Signed Audit Log Info Certificate Value
+ *
+ * This method is called to obtain the certificate from the passed in
+ * "X509CertImpl" for a signed audit log message.
+ * <P>
+ *
+ * @param x509cert an X509CertImpl
+ * @return cert string containing the certificate
+ */
+ protected String auditInfoCertValue(X509CertImpl x509cert) {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) {
+ return null;
+ }
+
+ if (x509cert == null) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ byte rawData[] = null;
+
+ try {
+ rawData = x509cert.getEncoded();
+ } catch (CertificateEncodingException e) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ String cert = null;
+
+ // convert "rawData" into "base64Data"
+ if (rawData != null) {
+ String base64Data = null;
+
+ base64Data = Utils.base64encode(rawData).trim();
+
+ // extract all line separators from the "base64Data"
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < base64Data.length(); i++) {
+ if (!Character.isWhitespace(base64Data.charAt(i))) {
+ sb.append(base64Data.charAt(i));
+ }
+ }
+ cert = sb.toString();
+ }
+
+ if (cert != null) {
+ cert = cert.trim();
+
+ if (cert.equals("")) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ } else {
+ return cert;
+ }
+ } else {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+
+ /**
+ * Signed Audit Groups
+ *
+ * This method is called to extract all "groups" associated
+ * with the "auditSubjectID()".
+ * <P>
+ *
+ * @param SubjectID string containing the signed audit log message SubjectID
+ * @return a delimited string of groups associated
+ * with the "auditSubjectID()"
+ */
+ protected String auditGroups(String SubjectID) {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) {
+ return null;
+ }
+
+ if ((SubjectID == null) ||
+ (SubjectID.equals(ILogger.UNIDENTIFIED))) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ Enumeration<IGroup> groups = null;
+
+ try {
+ groups = ug.findGroups("*");
+ } catch (Exception e) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ StringBuffer membersString = new StringBuffer();
+
+ while (groups.hasMoreElements()) {
+ IGroup group = groups.nextElement();
+
+ if (group.isMember(SubjectID) == true) {
+ if (membersString.length() != 0) {
+ membersString.append(", ");
+ }
+
+ membersString.append(group.getGroupID());
+ }
+ }
+
+ if (membersString.length() != 0) {
+ return membersString.toString();
+ } else {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+}