summaryrefslogtreecommitdiffstats
path: root/base/server/cms/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'base/server/cms/src/com')
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/ExternalProcessConstraint.java178
1 files changed, 178 insertions, 0 deletions
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/ExternalProcessConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/ExternalProcessConstraint.java
new file mode 100644
index 000000000..8fb91ab0e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/ExternalProcessConstraint.java
@@ -0,0 +1,178 @@
+// --- 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) 2016, 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.profile.constraint;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.io.IOUtils;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.input.CertReqInput;
+
+import netscape.security.x509.X509CertInfo;
+
+
+public class ExternalProcessConstraint extends EnrollConstraint {
+
+ public static final String CONFIG_EXECUTABLE = "executable";
+ public static final String CONFIG_TIMEOUT = "timeout";
+
+ public static final long DEFAULT_TIMEOUT = 10;
+
+ /* Map of envvars to include, and the corresponding IRequest keys
+ *
+ * All keys will be prefixed with "DOGTAG_" when added to environment.
+ */
+ protected static final Map<String, String> envVars = new TreeMap<>();
+
+ protected Map<String, String> extraEnvVars = new TreeMap<>();
+
+ static {
+ envVars.put("DOGTAG_CERT_REQUEST", CertReqInput.VAL_CERT_REQUEST);
+ envVars.put("DOGTAG_USER",
+ IRequest.AUTH_TOKEN_PREFIX + "." + IAuthToken.USER_ID);
+ envVars.put("DOGTAG_PROFILE_ID", IRequest.PROFILE_ID);
+ envVars.put("DOGTAG_AUTHORITY_ID", IRequest.AUTHORITY_ID);
+ envVars.put("DOGTAG_USER_DATA", IRequest.USER_DATA);
+ }
+
+ protected String executable;
+ protected long timeout;
+
+ public ExternalProcessConstraint() {
+ addConfigName(CONFIG_EXECUTABLE);
+ addConfigName(CONFIG_TIMEOUT);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+
+ this.executable = getConfig(CONFIG_EXECUTABLE);
+ if (this.executable == null || this.executable.isEmpty()) {
+ throw new EProfileException(
+ "Missing required config param 'executable'");
+ }
+
+ timeout = DEFAULT_TIMEOUT;
+ String timeoutConfig = getConfig(CONFIG_TIMEOUT);
+ if (this.executable != null && !this.executable.isEmpty()) {
+ try {
+ timeout = (new Integer(timeoutConfig)).longValue();
+ } catch (NumberFormatException e) {
+ throw new EProfileException("Invalid timeout value", e);
+ }
+ if (timeout < 1) {
+ throw new EProfileException(
+ "Invalid timeout value: must be positive");
+ }
+ }
+
+ IConfigStore envConfig = config.getSubStore("params.env");
+ Enumeration<String> names = envConfig.getPropertyNames();
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ try {
+ extraEnvVars.put(name, envConfig.getString(name));
+ } catch (EBaseException e) {
+ // shouldn't happen; log and move on
+ CMS.debug(
+ "ExternalProcessConstraint: caught exception processing "
+ + "'params.env' config: " + e
+ );
+
+ }
+ }
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_EXECUTABLE)) {
+ return new Descriptor(
+ IDescriptor.STRING, null, null, "Executable path");
+ } else if (name.equals(CONFIG_TIMEOUT)) {
+ return new Descriptor(
+ IDescriptor.INTEGER, null, null, "Timeout in seconds");
+ } else {
+ return null;
+ }
+ }
+
+ public void validate(IRequest request, X509CertInfo info)
+ throws ERejectException {
+ CMS.debug("About to execute command: " + this.executable);
+ ProcessBuilder pb = new ProcessBuilder(this.executable);
+
+ // set up process environment
+ Map<String, String> env = pb.environment();
+ for (String k : envVars.keySet()) {
+ String v = request.getExtDataInString(envVars.get(k));
+ if (v != null)
+ env.put(k, v);
+ }
+ for (String k : extraEnvVars.keySet()) {
+ String v = request.getExtDataInString(extraEnvVars.get(k));
+ if (v != null)
+ env.put(k, v);
+ }
+
+ Process p;
+ String stdout = "";
+ String stderr = "";
+ boolean timedOut;
+ try {
+ p = pb.start();
+ timedOut = !p.waitFor(timeout, TimeUnit.SECONDS);
+ if (timedOut)
+ p.destroyForcibly();
+ else
+ stdout = IOUtils.toString(p.getInputStream());
+ stderr = IOUtils.toString(p.getErrorStream());
+ } catch (Throwable e) {
+ String msg =
+ "Caught exception while executing command: " + this.executable;
+ CMS.debug(msg);
+ CMS.debug(e);
+ throw new ERejectException(msg, e);
+ }
+ if (timedOut)
+ throw new ERejectException("Request validation timed out");
+ int exitValue = p.exitValue();
+ CMS.debug("ExternalProcessConstraint: exit value: " + exitValue);
+ CMS.debug("ExternalProcessConstraint: stdout: " + stdout);
+ CMS.debug("ExternalProcessConstraint: stderr: " + stderr);
+ if (exitValue != 0)
+ throw new ERejectException(stdout);
+ }
+
+}