From 6c52845955315ca8842290d41c826c26aa037eb3 Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Wed, 25 May 2016 18:10:59 -0400
Subject: [PATCH 315/319] Fix old KRA servlets to check realm

The old KRA servlets to list and display keys do not go through
the same code paths as the REST API.  Therefore, they do not
check the authz realm.

This patch adds the relevant code.  No attempt is made to fix the
error handling of the old servlets.  the long term solution for this
is to deprecate the old servlets and make the UI use the REST API
instead.  Therefore, authz failures due to realm checks are handled
in the same way as other authz changes.
---
 .../netscape/cms/servlet/key/DisplayBySerial.java  | 16 +++++++--
 .../servlet/key/DisplayBySerialForRecovery.java    | 16 +++++++--
 .../src/com/netscape/cms/servlet/key/SrchKey.java  | 40 +++++++++++++++++++---
 .../cms/servlet/key/SrchKeyForRecovery.java        | 38 +++++++++++++++++---
 4 files changed, 96 insertions(+), 14 deletions(-)

diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerial.java b/base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerial.java
index 03af65c1f6df3a49408c42c8df6a009337d96f2f..7d3a5e9ff1c1886abde5e3cfe98b6338c9008db2 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerial.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerial.java
@@ -31,6 +31,7 @@ import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.authorization.AuthzToken;
 import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.authorization.EAuthzException;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.IArgBlock;
 import com.netscape.certsrv.common.ICMSRequest;
@@ -154,7 +155,12 @@ public class DisplayBySerial extends CMSServlet {
             if (req.getParameter(IN_SERIALNO) != null) {
                 seqNum = new BigInteger(req.getParameter(IN_SERIALNO));
             }
-            process(argSet, header, seqNum, req, resp, locale[0]);
+            process(argSet, header, seqNum, req, resp, locale[0], authToken);
+        } catch (EAuthzException e) {
+            log(ILogger.LL_FAILURE,
+                    CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+            cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+            return;
         } catch (NumberFormatException e) {
             header.addStringValue(OUT_ERROR,
                     CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString()));
@@ -175,19 +181,23 @@ public class DisplayBySerial extends CMSServlet {
 
     /**
      * Display information about a particular key.
+     * @throws EAuthzException
      */
     private void process(CMSTemplateParams argSet,
             IArgBlock header, BigInteger seq,
             HttpServletRequest req, HttpServletResponse resp,
-            Locale locale) {
+            Locale locale, IAuthToken authToken) throws EAuthzException {
         try {
             header.addStringValue(OUT_OP,
                     req.getParameter(OUT_OP));
             header.addStringValue(OUT_SERVICE_URL,
                     req.getRequestURI());
             IKeyRecord rec = mKeyDB.readKeyRecord(seq);
-
+            mAuthz.checkRealm(rec.getRealm(), authToken, rec.getOwnerName(),
+                    mAuthzResourceName, "read");
             KeyRecordParser.fillRecordIntoArg(rec, header);
+        } catch (EAuthzException e) {
+            throw e;
         } catch (EBaseException e) {
             header.addStringValue(OUT_ERROR, e.toString(locale));
         }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerialForRecovery.java b/base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerialForRecovery.java
index 48cac3785fd3868b14296c9f44b53e00e8493f87..fdba138a24fefd1e9042b3b29789cd134899b8ff 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerialForRecovery.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerialForRecovery.java
@@ -31,6 +31,7 @@ import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.authorization.AuthzToken;
 import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.authorization.EAuthzException;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.IArgBlock;
 import com.netscape.certsrv.common.ICMSRequest;
@@ -159,7 +160,12 @@ public class DisplayBySerialForRecovery extends CMSServlet {
             }
             process(argSet, header,
                     req.getParameter("publicKeyData"),
-                    seqNum, req, resp, locale[0]);
+                    seqNum, req, resp, locale[0], authToken);
+        } catch (EAuthzException e) {
+                log(ILogger.LL_FAILURE,
+                        CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+                cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+                return;
         } catch (NumberFormatException e) {
             header.addStringValue(OUT_ERROR,
                     CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString()));
@@ -183,11 +189,12 @@ public class DisplayBySerialForRecovery extends CMSServlet {
 
     /**
      * Display information about a particular key.
+     * @throws EAuthzException
      */
     private synchronized void process(CMSTemplateParams argSet,
             IArgBlock header, String publicKeyData, BigInteger seq,
             HttpServletRequest req, HttpServletResponse resp,
-            Locale locale) {
+            Locale locale, IAuthToken authToken) throws EAuthzException {
         try {
             header.addIntegerValue("noOfRequiredAgents",
                     mService.getNoOfRequiredAgents());
@@ -202,11 +209,14 @@ public class DisplayBySerialForRecovery extends CMSServlet {
                         publicKeyData);
             }
             IKeyRecord rec = mKeyDB.readKeyRecord(seq);
-
+            mAuthz.checkRealm(rec.getRealm(), authToken, rec.getOwnerName(),
+                    mAuthzResourceName, "read");
             KeyRecordParser.fillRecordIntoArg(rec, header);
 
             // recovery identifier
             header.addStringValue("recoveryID", mService.getRecoveryID());
+        } catch (EAuthzException e) {
+            throw e;
         } catch (EBaseException e) {
             header.addStringValue(OUT_ERROR, e.toString(locale));
         }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/SrchKey.java b/base/server/cms/src/com/netscape/cms/servlet/key/SrchKey.java
index 5bedf1f588186ded0d3070eec1285961a26b0dde..73a8051adc002dee5e3edc5a2fa15d16b6412658 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/key/SrchKey.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/SrchKey.java
@@ -27,12 +27,11 @@ import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import netscape.security.x509.X500Name;
-
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.authorization.AuthzToken;
 import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.authorization.EAuthzException;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.IArgBlock;
 import com.netscape.certsrv.common.ICMSRequest;
@@ -45,6 +44,9 @@ import com.netscape.cms.servlet.common.CMSRequest;
 import com.netscape.cms.servlet.common.CMSTemplate;
 import com.netscape.cms.servlet.common.CMSTemplateParams;
 import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+import netscape.security.x509.X500Name;
 
 /**
  * Retrieve archived keys matching search criteria
@@ -65,6 +67,7 @@ public class SrchKey extends CMSServlet {
     private final static String IN_MAXCOUNT = "maxCount";
     private final static String IN_FILTER = "queryFilter";
     private final static String IN_SENTINEL = "querySentinel";
+    private final static String REALM = "realm";
 
     // output parameters
     private final static String OUT_FILTER = IN_FILTER;
@@ -144,6 +147,7 @@ public class SrchKey extends CMSServlet {
      * <li>http.param queryFilter ldap-style filter to search with
      * <li>http.param querySentinel ID of first request to show
      * <li>http.param timeLimit number of seconds to limit ldap search to
+     * <li>http.param realm authorization realm to search
      * </ul>
      *
      * @param cmsReq the object holding the request and response information
@@ -173,6 +177,22 @@ public class SrchKey extends CMSServlet {
             return;
         }
 
+        String realm = req.getParameter(REALM);
+        try {
+            mAuthz.checkRealm(realm, authToken, null, mAuthzResourceName, "list");
+        } catch (EAuthzException e) {
+            log(ILogger.LL_FAILURE,
+                    CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+            cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+            return;
+        } catch (EBaseException e) {
+            log(ILogger.LL_FAILURE,
+                    CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+            cmsReq.setStatus(ICMSRequest.EXCEPTION);
+            return;
+        }
+
+
         CMSTemplate form = null;
         Locale[] locale = new Locale[1];
 
@@ -212,9 +232,10 @@ public class SrchKey extends CMSServlet {
 
             if (timeLimitStr != null && timeLimitStr.length() > 0)
                 timeLimit = Integer.parseInt(timeLimitStr);
+
             process(argSet, header, ctx, maxCount, maxResults,
                     timeLimit, sentinel,
-                    req.getParameter(IN_FILTER), req, resp, locale[0]);
+                    req.getParameter(IN_FILTER), req, resp, locale[0], realm);
         } catch (NumberFormatException e) {
             header.addStringValue(OUT_ERROR,
                     CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString()));
@@ -240,9 +261,19 @@ public class SrchKey extends CMSServlet {
     private void process(CMSTemplateParams argSet,
             IArgBlock header, IArgBlock ctx,
             int maxCount, int maxResults, int timeLimit, int sentinel, String filter,
-            HttpServletRequest req, HttpServletResponse resp, Locale locale) {
+            HttpServletRequest req, HttpServletResponse resp, Locale locale, String realm) {
 
         try {
+            if (filter.contains("(realm=)")) {
+                throw new EBaseException("Query filter cannot contain realm");
+            }
+
+            if (realm != null) {
+                filter = "(&" + filter + "(realm=" + LDAPUtil.escapeFilter(realm) +"))";
+            } else {
+                filter = "(&" + filter + "(!(realm=*)))";
+            }
+
             // Fill header
             header.addStringValue(OUT_OP,
                     req.getParameter(OUT_OP));
@@ -263,6 +294,7 @@ public class SrchKey extends CMSServlet {
                 CMS.debug("Resetting timelimit from " + timeLimit + " to " + mTimeLimits);
                 timeLimit = mTimeLimits;
             }
+
             CMS.debug("Start searching ... timelimit=" + timeLimit);
             Enumeration<IKeyRecord> e = mKeyDB.searchKeys(filter,
                     maxResults, timeLimit);
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/SrchKeyForRecovery.java b/base/server/cms/src/com/netscape/cms/servlet/key/SrchKeyForRecovery.java
index 897acfc764f5d72fad6710708b2cc40063578129..6ecf2b0561218c409d689bbf5a69638cd479524f 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/key/SrchKeyForRecovery.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/SrchKeyForRecovery.java
@@ -27,12 +27,11 @@ import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import netscape.security.x509.X500Name;
-
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.authorization.AuthzToken;
 import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.authorization.EAuthzUnknownRealm;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.IArgBlock;
 import com.netscape.certsrv.common.ICMSRequest;
@@ -45,6 +44,9 @@ import com.netscape.cms.servlet.common.CMSRequest;
 import com.netscape.cms.servlet.common.CMSTemplate;
 import com.netscape.cms.servlet.common.CMSTemplateParams;
 import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+import netscape.security.x509.X500Name;
 
 /**
  * Retrieve archived keys matching given public key material
@@ -66,6 +68,7 @@ public class SrchKeyForRecovery extends CMSServlet {
     private final static String IN_MAXCOUNT = "maxCount";
     private final static String IN_FILTER = "queryFilter";
     private final static String IN_SENTINEL = "querySentinel";
+    private final static String REALM = "realm";
 
     // output parameters
     private final static String OUT_FILTER = IN_FILTER;
@@ -142,6 +145,7 @@ public class SrchKeyForRecovery extends CMSServlet {
      * <li>http.param publicKeyData public key data to search on
      * <li>http.param querySentinel ID of first request to show
      * <li>http.param timeLimit number of seconds to limit ldap search to
+     * <li>http.param realm authorization realm to search
      * </ul>
      *
      * @param cmsReq the object holding the request and response information
@@ -171,6 +175,21 @@ public class SrchKeyForRecovery extends CMSServlet {
             return;
         }
 
+        String realm = req.getParameter(REALM);
+        try {
+            mAuthz.checkRealm(realm, authToken, null, mAuthzResourceName, "list");
+        } catch (EAuthzAccessDenied | EAuthzUnknownRealm e) {
+            log(ILogger.LL_FAILURE,
+                    CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+            cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+            return;
+        } catch (EBaseException e) {
+            log(ILogger.LL_FAILURE,
+                    CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+            cmsReq.setStatus(ICMSRequest.EXCEPTION);
+            return;
+        }
+
         CMSTemplate form = null;
         Locale[] locale = new Locale[1];
 
@@ -212,7 +231,8 @@ public class SrchKeyForRecovery extends CMSServlet {
             if (timeLimitStr != null && timeLimitStr.length() > 0)
                 timeLimit = Integer.parseInt(timeLimitStr);
             process(argSet, header, ctx, maxCount, maxResults, timeLimit, sentinel,
-                    req.getParameter("publicKeyData"), req.getParameter(IN_FILTER), req, resp, locale[0]);
+                    req.getParameter("publicKeyData"), req.getParameter(IN_FILTER),
+                    req, resp, locale[0], realm);
         } catch (NumberFormatException e) {
             log(ILogger.LL_FAILURE,
                     CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT"));
@@ -255,10 +275,20 @@ public class SrchKeyForRecovery extends CMSServlet {
             IArgBlock header, IArgBlock ctx,
             int maxCount, int maxResults, int timeLimit, int sentinel, String publicKeyData,
             String filter,
-            HttpServletRequest req, HttpServletResponse resp, Locale locale)
+            HttpServletRequest req, HttpServletResponse resp, Locale locale, String realm)
             throws EBaseException {
 
         try {
+            if (filter.contains("(realm=)")) {
+                throw new EBaseException("Query filter cannot contain realm");
+            }
+
+            if (realm != null) {
+                filter = "(&" + filter + "(realm=" + LDAPUtil.escapeFilter(realm) +"))";
+            } else {
+                filter = "(&" + filter + "(!(realm=*)))";
+            }
+
             // Fill header
             header.addStringValue(OUT_OP,
                     req.getParameter(OUT_OP));
-- 
2.4.3

