From 9d5df1af34dadab27ec54779b5b68a1d3bbedbac Mon Sep 17 00:00:00 2001
From: Endi Sukma Dewata <edewata@redhat.com>
Date: Sat, 19 May 2012 10:52:07 -0500
Subject: [PATCH] Added Auditor service.

A new Auditor service has been added to replace the audit service that was
previously only available to subclasses of AdminServlet. The new service
can be used by other components including REST services. The AdminServlet
will be modified to use the Auditor service separately.

Ticket #160
---
 base/common/src/CMakeLists.txt                     |    2 +
 base/common/src/com/netscape/certsrv/apps/CMS.java |   12 +
 .../src/com/netscape/certsrv/apps/ICMSEngine.java  |   10 +
 .../src/com/netscape/certsrv/logging/IAuditor.java |   78 +++++++
 .../src/com/netscape/cmscore/apps/CMSEngine.java   |    6 +
 .../src/com/netscape/cmscore/logging/Auditor.java  |  212 ++++++++++++++++++++
 .../netscape/certsrv/app/CMSEngineDefaultStub.java |    5 +
 7 files changed, 325 insertions(+), 0 deletions(-)
 create mode 100644 base/common/src/com/netscape/certsrv/logging/IAuditor.java
 create mode 100644 base/common/src/com/netscape/cmscore/logging/Auditor.java

diff --git a/base/common/src/CMakeLists.txt b/base/common/src/CMakeLists.txt
index 0a9fcddfb85ddf1f52a01ab3c595c14b799071b6..8ca357c7f98f885cc13fd1dec5f06081cb29e451 100644
--- a/base/common/src/CMakeLists.txt
+++ b/base/common/src/CMakeLists.txt
@@ -351,6 +351,7 @@ set(pki-certsrv_java_SRCS
     com/netscape/certsrv/logging/ELogException.java
     com/netscape/certsrv/logging/ConsoleLog.java
     com/netscape/certsrv/logging/LogPlugin.java
+    com/netscape/certsrv/logging/IAuditor.java
     com/netscape/certsrv/logging/ILogSubsystem.java
     com/netscape/certsrv/logging/IBundleLogEvent.java
     com/netscape/certsrv/logging/ELogPluginNotFound.java
@@ -1037,6 +1038,7 @@ set(pki-cmscore_java_SRCS
     com/netscape/cmscore/logging/AuditEventFactory.java
     com/netscape/cmscore/logging/LogQueue.java
     com/netscape/cmscore/logging/LogSubsystem.java
+    com/netscape/cmscore/logging/Auditor.java
     com/netscape/cmscore/logging/AuditFormat.java
     com/netscape/cmscore/logging/Logger.java
     com/netscape/cmscore/logging/SignedAuditEventFactory.java
diff --git a/base/common/src/com/netscape/certsrv/apps/CMS.java b/base/common/src/com/netscape/certsrv/apps/CMS.java
index 4d45777778dfa416f93d21ee7ea944c3cc78f2c3..00d2e0653f50e1e8b211eb3ff5a22971ac8fa1e1 100644
--- a/base/common/src/com/netscape/certsrv/apps/CMS.java
+++ b/base/common/src/com/netscape/certsrv/apps/CMS.java
@@ -73,6 +73,7 @@ import com.netscape.certsrv.ldap.ELdapException;
 import com.netscape.certsrv.ldap.ILdapAuthInfo;
 import com.netscape.certsrv.ldap.ILdapConnFactory;
 import com.netscape.certsrv.ldap.ILdapConnInfo;
+import com.netscape.certsrv.logging.IAuditor;
 import com.netscape.certsrv.logging.ILogSubsystem;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.notification.IEmailFormProcessor;
@@ -288,6 +289,17 @@ public final class CMS {
     }
 
     /**
+     * Returns the auditor of the current server. The auditor can
+     * be used to audit critical informational or critical error
+     * messages.
+     *
+     * @return auditor
+     */
+    public static IAuditor getAuditor() {
+        return _engine.getAuditor();
+    }
+
+    /**
      * Returns the signed audit logger of the current server. This logger can
      * be used to log critical informational or critical error
      * messages.
diff --git a/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java b/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java
index 41f4c348e7b1524b95ed5fb329164f95ed41ae62..f11005c07edfc7a0b4f2ee80bcde06420a34096d 100644
--- a/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java
+++ b/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java
@@ -64,6 +64,7 @@ import com.netscape.certsrv.ldap.ELdapException;
 import com.netscape.certsrv.ldap.ILdapAuthInfo;
 import com.netscape.certsrv.ldap.ILdapConnFactory;
 import com.netscape.certsrv.ldap.ILdapConnInfo;
+import com.netscape.certsrv.logging.IAuditor;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.notification.IEmailFormProcessor;
 import com.netscape.certsrv.notification.IEmailResolver;
@@ -187,6 +188,15 @@ public interface ICMSEngine extends ISubsystem {
     public ILogger getLogger();
 
     /**
+     * Returns the auditor of the current server. The auditor can
+     * be used to audit critical informational or critical error
+     * messages.
+     *
+     * @return auditor
+     */
+    public IAuditor getAuditor();
+
+    /**
      * Returns the signed audit logger of the current server. This logger can
      * be used to log critical informational or critical error
      * messages.
diff --git a/base/common/src/com/netscape/certsrv/logging/IAuditor.java b/base/common/src/com/netscape/certsrv/logging/IAuditor.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9362259633e29d33f5ae8fc3efc86628c9ebe35
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/logging/IAuditor.java
@@ -0,0 +1,78 @@
+// --- 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.certsrv.logging;
+
+import java.util.Map;
+
+/**
+ * @author Endi S. Dewata
+ */
+public interface IAuditor {
+
+    public final static String LOGGING_SIGNED_AUDIT_CONFIG_ROLE =
+            "LOGGING_SIGNED_AUDIT_CONFIG_ROLE_3";
+
+    public final static String SIGNED_AUDIT_SCOPE = "Scope";
+    public final static String SIGNED_AUDIT_OPERATION = "Operation";
+    public final static String SIGNED_AUDIT_RESOURCE = "Resource";
+    public final static String SIGNED_AUDIT_RULENAME = "RULENAME";
+    public final static String SIGNED_AUDIT_PASSWORD_VALUE = "********";
+    public final static String SIGNED_AUDIT_EMPTY_NAME_VALUE_PAIR = "Unknown";
+    public final static String SIGNED_AUDIT_NAME_VALUE_DELIMITER = ";;";
+    public final static String SIGNED_AUDIT_NAME_VALUE_PAIRS_DELIMITER = "+";
+
+    /**
+     * Get signed audit log subject ID
+     *
+     * This method is called to obtain the "SubjectID" for
+     * a signed audit log message.
+     *
+     * @return id string containing the signed audit log message SubjectID
+     */
+    public String getSubjectID();
+
+    /**
+     * Get 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()"
+     */
+    public String getGroups(String subjectID);
+
+        /**
+     * Get signed audit parameters as a string.
+     *
+     * This method is called to convert parameters into a
+     * string of name;;value pairs separated by a '+'
+     * if more than one name;;value pair exists.
+     *
+     * @return a delimited string of one or more delimited name/value pairs
+     */
+    public String getParamString(String scope, String type, String id, Map<String, String> params);
+
+    /**
+     * Log audit message.
+     */
+    public void log(String message);
+}
\ No newline at end of file
diff --git a/base/common/src/com/netscape/cmscore/apps/CMSEngine.java b/base/common/src/com/netscape/cmscore/apps/CMSEngine.java
index 19fc5162b0f4ff43b1bec1ff6dc9004a2f6748ec..72e8c49e80f6b3aad6128b8cc6bf0a5a61953515 100644
--- a/base/common/src/com/netscape/cmscore/apps/CMSEngine.java
+++ b/base/common/src/com/netscape/cmscore/apps/CMSEngine.java
@@ -100,6 +100,7 @@ import com.netscape.certsrv.ldap.ILdapAuthInfo;
 import com.netscape.certsrv.ldap.ILdapConnFactory;
 import com.netscape.certsrv.ldap.ILdapConnInfo;
 import com.netscape.certsrv.logging.ELogException;
+import com.netscape.certsrv.logging.IAuditor;
 import com.netscape.certsrv.logging.ILogEvent;
 import com.netscape.certsrv.logging.ILogEventListener;
 import com.netscape.certsrv.logging.ILogQueue;
@@ -152,6 +153,7 @@ import com.netscape.cmscore.ldapconn.LdapBoundConnFactory;
 import com.netscape.cmscore.ldapconn.LdapBoundConnection;
 import com.netscape.cmscore.ldapconn.LdapConnInfo;
 import com.netscape.cmscore.ldapconn.LdapJssSSLSocketFactory;
+import com.netscape.cmscore.logging.Auditor;
 import com.netscape.cmscore.logging.LogSubsystem;
 import com.netscape.cmscore.logging.Logger;
 import com.netscape.cmscore.logging.SignedAuditLogger;
@@ -1513,6 +1515,10 @@ public class CMSEngine implements ICMSEngine {
         return Logger.getLogger();
     }
 
+    public IAuditor getAuditor() {
+        return Auditor.getAuditor();
+    }
+
     public ILogger getSignedAuditLogger() {
         return SignedAuditLogger.getLogger();
     }
diff --git a/base/common/src/com/netscape/cmscore/logging/Auditor.java b/base/common/src/com/netscape/cmscore/logging/Auditor.java
new file mode 100644
index 0000000000000000000000000000000000000000..eef4ad14b4e046b99e17ac9aa82af967d22f0688
--- /dev/null
+++ b/base/common/src/com/netscape/cmscore/logging/Auditor.java
@@ -0,0 +1,212 @@
+// --- 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.cmscore.logging;
+
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.logging.IAuditor;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class Auditor implements IAuditor {
+
+    public final static Auditor auditor = new Auditor();
+
+    public ILogger signedAuditLogger = CMS.getSignedAuditLogger();
+
+    public static IAuditor getAuditor() {
+        return auditor;
+    }
+
+    @Override
+    public String getSubjectID() {
+        // if no signed audit object exists, bail
+        if (signedAuditLogger == null) return null;
+
+        SessionContext context = SessionContext.getExistingContext();
+        if (context == null) return ILogger.UNIDENTIFIED;
+
+        // Initialize subject ID
+        String subjectID = (String)context.get(SessionContext.USER_ID);
+        if (subjectID == null) return ILogger.NONROLEUSER;
+
+        return subjectID.trim();
+    }
+
+    @Override
+    public String getGroups(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;
+
+        try {
+            IUGSubsystem userGroupSubsystem = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+            groups = userGroupSubsystem.findGroups("*");
+
+        } catch (Exception e) {
+            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+        }
+
+        StringBuilder sb = new StringBuilder();
+
+        while (groups.hasMoreElements()) {
+            IGroup group = groups.nextElement();
+
+            if (group.isMember(subjectID) == true) {
+                if (sb.length() != 0) sb.append(", ");
+                sb.append(group.getGroupID());
+            }
+        }
+
+        if (sb.length() == 0) return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+
+        return sb.toString();
+    }
+
+    @Override
+    public String getParamString(String scope, String type, String id, Map<String, String> params) {
+
+        // if no signed audit object exists, bail
+        if (signedAuditLogger == null) return null;
+
+        String parameters = SIGNED_AUDIT_EMPTY_NAME_VALUE_PAIR;
+
+        // always identify the scope of the request
+        if (scope != null) {
+            parameters = SIGNED_AUDIT_SCOPE
+                    + SIGNED_AUDIT_NAME_VALUE_DELIMITER
+                    + scope;
+        }
+
+        // identify the operation type of the request
+        if (type != null) {
+            parameters += SIGNED_AUDIT_NAME_VALUE_PAIRS_DELIMITER;
+
+            parameters += SIGNED_AUDIT_OPERATION
+                    + SIGNED_AUDIT_NAME_VALUE_DELIMITER
+                    + type;
+        }
+
+        // identify the resource type of the request
+        if (id != null) {
+            parameters += SIGNED_AUDIT_NAME_VALUE_PAIRS_DELIMITER;
+
+            parameters += SIGNED_AUDIT_RESOURCE
+                    + SIGNED_AUDIT_NAME_VALUE_DELIMITER
+                    + id;
+        }
+
+        if (params == null) return parameters;
+
+        // identify any remaining request parameters
+        Collection<String> names = params.keySet();
+
+        for (Iterator<String> i = names.iterator(); i.hasNext(); ) {
+            String name = i.next();
+
+            // skip "RULENAME" parameter
+            if (name.equals(SIGNED_AUDIT_RULENAME)) continue;
+
+            parameters += SIGNED_AUDIT_NAME_VALUE_PAIRS_DELIMITER;
+
+            String value = params.get(name);
+
+            if (value == null) {
+                parameters += name
+                        + SIGNED_AUDIT_NAME_VALUE_DELIMITER
+                        + ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+                continue;
+            }
+
+            value = value.trim();
+
+            if (value.equals("")) {
+                parameters += name
+                        + SIGNED_AUDIT_NAME_VALUE_DELIMITER
+                        + ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+                continue;
+            }
+
+            //
+            // To fix Blackflag Bug # 613800:
+            //
+            //     Check "com.netscape.certsrv.common.Constants" for
+            //     case-insensitive "password", "pwd", and "passwd"
+            //     name fields, and hide any password values:
+            //
+            if (name.equals(Constants.PASSWORDTYPE) || /* "password" */
+                    name.equals(Constants.TYPE_PASSWORD) ||
+                    name.equals(Constants.PR_USER_PASSWORD) ||
+                    name.equals(Constants.PT_OLD_PASSWORD) ||
+                    name.equals(Constants.PT_NEW_PASSWORD) ||
+                    name.equals(Constants.PT_DIST_STORE) ||
+                    name.equals(Constants.PT_DIST_EMAIL) ||
+                    /* "pwd" */name.equals(Constants.PR_AUTH_ADMIN_PWD) ||
+                    // ignore this one  name.equals( Constants.PR_BINDPWD_PROMPT )        ||
+                    name.equals(Constants.PR_DIRECTORY_MANAGER_PWD) ||
+                    name.equals(Constants.PR_OLD_AGENT_PWD) ||
+                    name.equals(Constants.PR_AGENT_PWD) ||
+                    name.equals(Constants.PT_PUBLISH_PWD) ||
+                    /* "passwd" */name.equals(Constants.PR_BIND_PASSWD) ||
+                    name.equals(Constants.PR_BIND_PASSWD_AGAIN) ||
+                    name.equals(Constants.PR_TOKEN_PASSWD)) {
+
+                // hide password value
+                parameters += name
+                            + SIGNED_AUDIT_NAME_VALUE_DELIMITER
+                            + SIGNED_AUDIT_PASSWORD_VALUE;
+
+            } else {
+                // process normally
+                parameters += name
+                            + SIGNED_AUDIT_NAME_VALUE_DELIMITER
+                            + value;
+            }
+        }
+
+        return parameters;
+    }
+
+    @Override
+    public void log(String message) {
+
+        if (signedAuditLogger == null) return;
+
+        signedAuditLogger.log(
+                ILogger.EV_SIGNED_AUDIT,
+                null,
+                ILogger.S_SIGNED_AUDIT,
+                ILogger.LL_SECURITY,
+                message);
+    }
+}
diff --git a/base/common/test/com/netscape/certsrv/app/CMSEngineDefaultStub.java b/base/common/test/com/netscape/certsrv/app/CMSEngineDefaultStub.java
index cddd1205a7f6bd42ce751b92c174b7bb83792e3f..ce5570667fde65a4e5a6ef34513aea9fef4641e5 100644
--- a/base/common/test/com/netscape/certsrv/app/CMSEngineDefaultStub.java
+++ b/base/common/test/com/netscape/certsrv/app/CMSEngineDefaultStub.java
@@ -49,6 +49,7 @@ import com.netscape.certsrv.ldap.ELdapException;
 import com.netscape.certsrv.ldap.ILdapAuthInfo;
 import com.netscape.certsrv.ldap.ILdapConnFactory;
 import com.netscape.certsrv.ldap.ILdapConnInfo;
+import com.netscape.certsrv.logging.IAuditor;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.notification.IEmailFormProcessor;
 import com.netscape.certsrv.notification.IEmailResolver;
@@ -142,6 +143,10 @@ public class CMSEngineDefaultStub implements ICMSEngine {
         return null;
     }
 
+    public IAuditor getAuditor() {
+        return null;
+    }
+
     public ILogger getSignedAuditLogger() {
         return null;
     }
-- 
1.7.7.6

